Final updates for 0.9.14.
[metze/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  * Portions based on information/specs retrieved from the OpenAFS sources at
9  *   www.openafs.org, Copyright IBM.
10  *
11  * $Id: packet-afs.c,v 1.54 2003/03/05 09:52:22 sahlberg Exp $
12  *
13  * Ethereal - Network traffic analyzer
14  * By Gerald Combs <gerald@ethereal.com>
15  * Copyright 1998 Gerald Combs
16  *
17  * Copied from packet-tftp.c
18  *
19  * This program is free software; you can redistribute it and/or
20  * modify it under the terms of the GNU General Public License
21  * as published by the Free Software Foundation; either version 2
22  * of the License, or (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program; if not, write to the Free Software
31  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
32  */
33
34 #ifdef HAVE_CONFIG_H
35 # include "config.h"
36 #endif
37
38 #include <stdio.h>
39
40 #include <string.h>
41 #include <glib.h>
42 #include <epan/packet.h>
43 #include <epan/conversation.h>
44 #include <epan/resolv.h>
45
46 #include "packet-rx.h"
47 #include "packet-afs.h"
48 #include "packet-afs-defs.h"
49 #include "packet-afs-macros.h"
50
51 #define GETSTR tvb_get_ptr(tvb,offset,tvb_ensure_length_remaining(tvb,offset))
52
53 #define VALID_OPCODE(opcode) ((opcode >= OPCODE_LOW && opcode <= OPCODE_HIGH) || \
54                 (opcode >= VOTE_LOW && opcode <= VOTE_HIGH) || \
55                 (opcode >= DISK_LOW && opcode <= DISK_HIGH))
56
57 static int afs_packet_init_count = 100;
58
59 struct afs_request_key {
60   guint32 conversation, callnumber;
61   guint16 service;
62 };
63
64 struct afs_request_val {
65   guint32 opcode;
66   guint req_num;
67   guint rep_num;
68   nstime_t req_time;
69 };
70
71 static GHashTable *afs_request_hash = NULL;
72 static GMemChunk *afs_request_keys = NULL;
73 static GMemChunk *afs_request_vals = NULL;
74
75
76
77 /*
78  * Dissector prototypes
79  */
80 static int dissect_acl(tvbuff_t *tvb, struct rxinfo *rxinfo,
81         proto_tree *tree, int offset);
82 static void dissect_fs_reply(tvbuff_t *tvb, struct rxinfo *rxinfo,
83         proto_tree *tree, int offset, int opcode);
84 static void dissect_fs_request(tvbuff_t *tvb, struct rxinfo *rxinfo,
85         proto_tree *tree, int offset, int opcode);
86 static void dissect_bos_reply(tvbuff_t *tvb, struct rxinfo *rxinfo,
87         proto_tree *tree, int offset, int opcode);
88 static void dissect_bos_request(tvbuff_t *tvb, struct rxinfo *rxinfo,
89         proto_tree *tree, int offset, int opcode);
90 static void dissect_vol_reply(tvbuff_t *tvb, struct rxinfo *rxinfo,
91         proto_tree *tree, int offset, int opcode);
92 static void dissect_vol_request(tvbuff_t *tvb, struct rxinfo *rxinfo,
93         proto_tree *tree, int offset, int opcode);
94 static void dissect_kauth_reply(tvbuff_t *tvb, struct rxinfo *rxinfo,
95         proto_tree *tree, int offset, int opcode);
96 static void dissect_kauth_request(tvbuff_t *tvb, struct rxinfo *rxinfo,
97         proto_tree *tree, int offset, int opcode);
98 static void dissect_cb_reply(tvbuff_t *tvb, struct rxinfo *rxinfo,
99         proto_tree *tree, int offset, int opcode);
100 static void dissect_cb_request(tvbuff_t *tvb, struct rxinfo *rxinfo,
101         proto_tree *tree, int offset, int opcode);
102 static void dissect_prot_reply(tvbuff_t *tvb, struct rxinfo *rxinfo,
103         proto_tree *tree, int offset, int opcode);
104 static void dissect_prot_request(tvbuff_t *tvb, struct rxinfo *rxinfo,
105         proto_tree *tree, int offset, int opcode);
106 static void dissect_vldb_reply(tvbuff_t *tvb, struct rxinfo *rxinfo,
107         proto_tree *tree, int offset, int opcode);
108 static void dissect_vldb_request(tvbuff_t *tvb, struct rxinfo *rxinfo,
109         proto_tree *tree, int offset, int opcode);
110 static void dissect_ubik_reply(tvbuff_t *tvb, struct rxinfo *rxinfo,
111         proto_tree *tree, int offset, int opcode);
112 static void dissect_ubik_request(tvbuff_t *tvb, struct rxinfo *rxinfo,
113         proto_tree *tree, int offset, int opcode);
114 static void dissect_backup_reply(tvbuff_t *tvb, struct rxinfo *rxinfo,
115         proto_tree *tree, int offset, int opcode);
116 static void dissect_backup_request(tvbuff_t *tvb, struct rxinfo *rxinfo,
117         proto_tree *tree, int offset, int opcode);
118
119 /*
120  * Hash Functions
121  */
122 static gint
123 afs_equal(gconstpointer v, gconstpointer w)
124 {
125   const struct afs_request_key *v1 = (const struct afs_request_key *)v;
126   const struct afs_request_key *v2 = (const struct afs_request_key *)w;
127
128   if (v1 -> conversation == v2 -> conversation &&
129       v1 -> service == v2 -> service &&
130       v1 -> callnumber == v2 -> callnumber ) {
131
132     return 1;
133   }
134
135   return 0;
136 }
137
138 static guint
139 afs_hash (gconstpointer v)
140 {
141         const struct afs_request_key *key = (const struct afs_request_key *)v;
142         guint val;
143
144         val = key -> conversation + key -> service + key -> callnumber;
145
146         return val;
147 }
148
149 /*
150  * Protocol initialization
151  */
152 static void
153 afs_init_protocol(void)
154 {
155         if (afs_request_hash)
156                 g_hash_table_destroy(afs_request_hash);
157         if (afs_request_keys)
158                 g_mem_chunk_destroy(afs_request_keys);
159         if (afs_request_vals)
160                 g_mem_chunk_destroy(afs_request_vals);
161
162         afs_request_hash = g_hash_table_new(afs_hash, afs_equal);
163         afs_request_keys = g_mem_chunk_new("afs_request_keys",
164                 sizeof(struct afs_request_key),
165                 afs_packet_init_count * sizeof(struct afs_request_key),
166                 G_ALLOC_AND_FREE);
167         afs_request_vals = g_mem_chunk_new("afs_request_vals",
168                 sizeof(struct afs_request_val),
169                 afs_packet_init_count * sizeof(struct afs_request_val),
170                 G_ALLOC_AND_FREE);
171 }
172
173
174
175 /*
176  * Dissection routines
177  */
178
179 static void
180 dissect_afs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
181 {
182         struct rxinfo *rxinfo = pinfo->private_data;
183         int reply = 0;
184         conversation_t *conversation;
185         struct afs_request_key request_key, *new_request_key;
186         struct afs_request_val *request_val=NULL;
187         proto_tree      *afs_tree, *afs_op_tree, *ti;
188         int port, node, typenode, opcode;
189         value_string const *vals;
190         int offset = 0;
191         nstime_t ns;
192
193         void (*dissector)(tvbuff_t *tvb, struct rxinfo *rxinfo, proto_tree *tree, int offset, int opcode);
194
195
196         if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
197                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "AFS (RX)");
198         }
199         if (check_col(pinfo->cinfo, COL_INFO)) {
200                 col_clear(pinfo->cinfo, COL_INFO);
201         }
202
203         reply = (rxinfo->flags & RX_CLIENT_INITIATED) == 0;
204         port = ((reply == 0) ? pinfo->destport : pinfo->srcport );
205
206         /*
207          * Find out what conversation this packet is part of.
208          * XXX - this should really be done by the transport-layer protocol,
209          * although for connectionless transports, we may not want to do that
210          * unless we know some higher-level protocol will want it - or we
211          * may want to do it, so you can say e.g. "show only the packets in
212          * this UDP 'connection'".
213          *
214          * Note that we don't have to worry about the direction this packet
215          * was going - the conversation code handles that for us, treating
216          * packets from A:X to B:Y as being part of the same conversation as
217          * packets from B:Y to A:X.
218          */
219         conversation = find_conversation(&pinfo->src, &pinfo->dst, pinfo->ptype,
220             pinfo->srcport, pinfo->destport, 0);
221         if (conversation == NULL) {
222                 /* It's not part of any conversation - create a new one. */
223                 conversation = conversation_new(&pinfo->src, &pinfo->dst,
224                         pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
225         }
226
227         request_key.conversation = conversation->index;
228         request_key.service = rxinfo->serviceid;
229         request_key.callnumber = rxinfo->callnumber;
230
231         request_val = (struct afs_request_val *) g_hash_table_lookup(
232                 afs_request_hash, &request_key);
233
234         /* only allocate a new hash element when it's a request */
235         opcode = 0;
236         if(!pinfo->fd->flags.visited){
237                 if ( !request_val && !reply) {
238                         new_request_key = g_mem_chunk_alloc(afs_request_keys);
239                         *new_request_key = request_key;
240
241                         request_val = g_mem_chunk_alloc(afs_request_vals);
242                         request_val -> opcode = tvb_get_ntohl(tvb, offset);
243                         request_val -> req_num = pinfo->fd->num;
244                         request_val -> rep_num = 0;
245                         request_val -> req_time.secs=pinfo->fd->abs_secs;
246                         request_val -> req_time.nsecs=pinfo->fd->abs_usecs*1000;
247
248                         g_hash_table_insert(afs_request_hash, new_request_key,
249                                 request_val);
250                 }
251                 if( request_val && reply ) {
252                         request_val -> rep_num = pinfo->fd->num;
253                 }
254         }
255
256         if ( request_val ) {
257                 opcode = request_val->opcode;
258         }
259
260
261         node = 0;
262         typenode = 0;
263         vals = NULL;
264         dissector = NULL;
265         switch (port) {
266                 case AFS_PORT_FS:
267                         typenode = hf_afs_fs;
268                         node = hf_afs_fs_opcode;
269                         vals = fs_req;
270                         dissector = reply ? dissect_fs_reply : dissect_fs_request;
271                         break;
272                 case AFS_PORT_CB:
273                         typenode = hf_afs_cb;
274                         node = hf_afs_cb_opcode;
275                         vals = cb_req;
276                         dissector = reply ? dissect_cb_reply : dissect_cb_request;
277                         break;
278                 case AFS_PORT_PROT:
279                         typenode = hf_afs_prot;
280                         node = hf_afs_prot_opcode;
281                         vals = prot_req;
282                         dissector = reply ? dissect_prot_reply : dissect_prot_request;
283                         break;
284                 case AFS_PORT_VLDB:
285                         typenode = hf_afs_vldb;
286                         node = hf_afs_vldb_opcode;
287                         vals = vldb_req;
288                         dissector = reply ? dissect_vldb_reply : dissect_vldb_request;
289                         break;
290                 case AFS_PORT_KAUTH:
291                         typenode = hf_afs_kauth;
292                         node = hf_afs_kauth_opcode;
293                         vals = kauth_req;
294                         dissector = reply ? dissect_kauth_reply : dissect_kauth_request;
295                         break;
296                 case AFS_PORT_VOL:
297                         typenode = hf_afs_vol;
298                         node = hf_afs_vol_opcode;
299                         vals = vol_req;
300                         dissector = reply ? dissect_vol_reply : dissect_vol_request;
301                         break;
302                 case AFS_PORT_ERROR:
303                         typenode = hf_afs_error;
304                         node = hf_afs_error_opcode;
305                         /* dissector = reply ? dissect_error_reply : dissect_error_request; */
306                         break;
307                 case AFS_PORT_BOS:
308                         typenode = hf_afs_bos;
309                         node = hf_afs_bos_opcode;
310                         vals = bos_req;
311                         dissector = reply ? dissect_bos_reply : dissect_bos_request;
312                         break;
313                 case AFS_PORT_UPDATE:
314                         typenode = hf_afs_update;
315                         node = hf_afs_update_opcode;
316                         vals = update_req;
317                         /* dissector = reply ? dissect_update_reply : dissect_update_request; */
318                         break;
319                 case AFS_PORT_RMTSYS:
320                         typenode = hf_afs_rmtsys;
321                         node = hf_afs_rmtsys_opcode;
322                         vals = rmtsys_req;
323                         /* dissector = reply ? dissect_rmtsys_reply : dissect_rmtsys_request; */
324                         break;
325                 case AFS_PORT_BACKUP:
326                         typenode = hf_afs_backup;
327                         node = hf_afs_backup_opcode;
328                         vals = backup_req;
329                         dissector = reply ? dissect_backup_reply : dissect_backup_request;
330                         break;
331         }
332
333         if ( (opcode >= VOTE_LOW && opcode <= VOTE_HIGH) ||
334                 (opcode >= DISK_LOW && opcode <= DISK_HIGH) ) {
335                 typenode = hf_afs_ubik;
336                 node = hf_afs_ubik_opcode;
337                 vals = ubik_req;
338                 dissector = reply ? dissect_ubik_reply : dissect_ubik_request;
339         }
340
341
342         if ( VALID_OPCODE(opcode) ) {
343                 if ( vals ) {
344                         if (check_col(pinfo->cinfo, COL_INFO))
345                                 col_add_fstr(pinfo->cinfo, COL_INFO, "%s%s %s: %s (%d)",
346                                 typenode == hf_afs_ubik ? "UBIK-" : "",
347                                 val_to_str(port, port_types_short, "Unknown(%d)"),
348                                 reply ? "Reply" : "Request",
349                                 val_to_str(opcode, vals, "Unknown(%d)"), opcode);
350                 } else {
351                         if (check_col(pinfo->cinfo, COL_INFO))
352                                 col_add_fstr(pinfo->cinfo, COL_INFO, "%s%s %s: Unknown(%d)",
353                                 typenode == hf_afs_ubik ? "UBIK-" : "",
354                                 val_to_str(port, port_types_short, "Unknown(%d)"),
355                                 reply ? "Reply" : "Request",
356                                 opcode);
357                 }
358         } else {
359                 if (check_col(pinfo->cinfo, COL_INFO))
360                         col_add_fstr(pinfo->cinfo, COL_INFO, "Encrypted %s %s",
361                         val_to_str(port, port_types_short, "Unknown(%d)"),
362                         reply ? "Reply" : "Request"
363                         );
364         }
365
366         if (tree) {
367                 ti = proto_tree_add_item(tree, proto_afs, tvb, offset, -1,
368                                 FALSE);
369                 afs_tree = proto_item_add_subtree(ti, ett_afs);
370
371                 proto_tree_add_text(afs_tree, tvb,
372                         offset, -1,
373                         "Service: %s%s%s %s",
374                         VALID_OPCODE(opcode) ? "" : "Encrypted ",
375                         typenode == hf_afs_ubik ? "UBIK - " : "",
376                         val_to_str(port, port_types, "Unknown(%d)"),
377                         reply ? "Reply" : "Request");
378
379                 if( request_val && !reply && request_val->rep_num) {
380                         proto_tree_add_uint_format(afs_tree, hf_afs_repframe,
381                             tvb, 0, 0, request_val->rep_num,
382                             "The reply to this request is in frame %u",
383                             request_val->rep_num);
384                 }
385                 if( request_val && reply && request_val->rep_num) {
386                         proto_tree_add_uint_format(afs_tree, hf_afs_reqframe,
387                             tvb, 0, 0, request_val->req_num,
388                             "This is a reply to a request in frame %u",
389                             request_val->req_num);
390                         ns.secs= pinfo->fd->abs_secs-request_val->req_time.secs;
391                         ns.nsecs=pinfo->fd->abs_usecs*1000-request_val->req_time.nsecs;
392                         if(ns.nsecs<0){
393                                 ns.nsecs+=1000000000;
394                                 ns.secs--;
395                         }
396                         proto_tree_add_time(afs_tree, hf_afs_time, tvb, offset, 0,
397                                 &ns);
398                 }
399
400
401                 if ( VALID_OPCODE(opcode) ) {
402                         /* until we do cache, can't handle replies */
403                         ti = NULL;
404                         if ( !reply && node != 0 ) {
405                                 if ( rxinfo->seq == 1 )
406                                 {
407                                         ti = proto_tree_add_uint(afs_tree,
408                                                 node, tvb, offset, 4, opcode);
409                                 } else {
410                                         ti = proto_tree_add_uint(afs_tree,
411                                                 node, tvb, offset, 0, opcode);
412                                 }
413                         } else if ( reply && node != 0 ) {
414                                 /* the opcode isn't in this packet */
415                                 ti = proto_tree_add_uint(afs_tree,
416                                         node, tvb, offset, 0, opcode);
417                         } else {
418                                 ti = proto_tree_add_text(afs_tree, tvb,
419                                         offset, 0, "Operation: Unknown");
420                         }
421
422                         /* Add the subtree for this particular service */
423                         afs_op_tree = proto_item_add_subtree(ti, ett_afs_op);
424
425                         
426                         if ( typenode != 0 ) {
427                                 /* indicate the type of request */
428                                 proto_tree_add_boolean_hidden(afs_tree, typenode, tvb, offset, 0, 1);
429                         }
430
431                         /* Process the packet according to what service it is */
432                         if ( dissector ) {
433                                 (*dissector)(tvb, rxinfo, afs_op_tree, offset, opcode);
434                         }
435                 }
436         }
437
438         /* if it's the last packet, and it's a reply, remove opcode
439                 from hash */
440         /* ignoring for now, I'm not sure how the chunk deallocation works */
441         if ( rxinfo->flags & RX_LAST_PACKET && reply ){
442
443         }
444 }
445
446
447 /*
448  * Here is a helper routine for adding an AFS acl to the proto tree
449  * This is to be used with FS packets only
450  *
451  * An AFS ACL is a string that has the following format:
452  *
453  * <positive> <negative>
454  * <uid1> <aclbits1>
455  * ....
456  *
457  * "positive" and "negative" are integers which contain the number of
458  * positive and negative ACL's in the string.  The uid/aclbits pair are
459  * ASCII strings containing the UID/PTS record and and a ascii number
460  * representing a logical OR of all the ACL permission bits
461  */
462 /*
463  * XXX - FIXME:
464  *
465  *      sscanf is probably quite dangerous if we run outside the packet.
466  *
467  *      "GETSTR" doesn't guarantee that the resulting string is
468  *      null-terminated.
469  *
470  * Should this just scan the string itself, rather than using "sscanf()"?
471  */
472 static int
473 dissect_acl(tvbuff_t *tvb, struct rxinfo *rxinfo _U_, proto_tree *tree, int offset)
474 {
475         int old_offset;
476         gint32 bytes;
477         int i, n, pos, neg, acl;
478         char user[128]; /* Be sure to adjust sscanf()s below if length is changed... */
479
480         old_offset = offset;
481         bytes = tvb_get_ntohl(tvb, offset);
482         OUT_UINT(hf_afs_fs_acl_datasize);
483
484
485         if (sscanf(GETSTR, "%d %n", &pos, &n) != 1) {
486                 /* does not matter what we return, if this fails,
487                  * we cant dissect anything else in the packet either.
488                  */
489                 return offset;
490         }
491         proto_tree_add_uint(tree, hf_afs_fs_acl_count_positive, tvb,
492                 offset, n, pos);
493         offset += n;
494
495
496         if (sscanf(GETSTR, "%d %n", &neg, &n) != 1) {
497                 return offset;
498         }
499         proto_tree_add_uint(tree, hf_afs_fs_acl_count_negative, tvb,
500                 offset, n, neg);
501         offset += n;
502
503         /*
504          * This wacky order preserves the order used by the "fs" command
505          */
506         for (i = 0; i < pos; i++) {
507                 if (sscanf(GETSTR, "%127s %d %n", user, &acl, &n) != 2) {
508                         return offset;
509                 }
510                 ACLOUT(user,1,acl,n);
511                 offset += n;
512         }
513         for (i = 0; i < neg; i++) {
514                 if (sscanf(GETSTR, "%127s %d %n", user, &acl, &n) != 2) {
515                         return offset;
516                 }
517                 ACLOUT(user,0,acl,n);
518                 offset += n;
519                 if (offset >= old_offset+bytes ) {
520                         return offset;
521                 }
522         }
523
524         return offset;
525 }
526
527 /*
528  * Here are the helper dissection routines
529  */
530
531 static void
532 dissect_fs_reply(tvbuff_t *tvb, struct rxinfo *rxinfo, proto_tree *tree, int offset, int opcode)
533 {
534         if ( rxinfo->type == RX_PACKET_TYPE_DATA )
535         {
536                 switch ( opcode )
537                 {
538                         case 130: /* fetch data */
539                                 /* only on first packet */
540                                 if ( rxinfo->seq == 1 )
541                                 {
542                                         OUT_FS_AFSFetchStatus("Status");
543                                         OUT_FS_AFSCallBack();
544                                         OUT_FS_AFSVolSync();
545                                 }
546                                 OUT_BYTES_ALL(hf_afs_fs_data);
547                                 break;
548                         case 131: /* fetch acl */
549                                 offset = dissect_acl(tvb, rxinfo, tree, offset);
550                                 OUT_FS_AFSFetchStatus("Status");
551                                 OUT_FS_AFSVolSync();
552                                 break;
553                         case 132: /* Fetch status */
554                                 OUT_FS_AFSFetchStatus("Status");
555                                 OUT_FS_AFSCallBack();
556                                 OUT_FS_AFSVolSync();
557                                 break;
558                         case 133: /* Store data */
559                         case 134: /* Store ACL */
560                         case 135: /* Store status */
561                         case 136: /* Remove file */
562                                 OUT_FS_AFSFetchStatus("Status");
563                                 OUT_FS_AFSVolSync();
564                                 break;
565                         case 137: /* create file */
566                         case 141: /* make dir */
567                         case 161: /* lookup */
568                         case 163: /* dfs symlink */
569                                 OUT_FS_AFSFid((opcode == 137)? "New File" : ((opcode == 141)? "New Directory" : "File"));
570                                 OUT_FS_AFSFetchStatus("File Status");
571                                 OUT_FS_AFSFetchStatus("Directory Status");
572                                 OUT_FS_AFSCallBack();
573                                 OUT_FS_AFSVolSync();
574                                 break;
575                         case 138: /* rename */
576                                 OUT_FS_AFSFetchStatus("Old Directory Status");
577                                 OUT_FS_AFSFetchStatus("New Directory Status");
578                                 OUT_FS_AFSVolSync();
579                                 break;
580                         case 139: /* symlink */
581                                 OUT_FS_AFSFid("Symlink");
582                         case 140: /* link */
583                                 OUT_FS_AFSFetchStatus("Symlink Status");
584                         case 142: /* rmdir */
585                                 OUT_FS_AFSFetchStatus("Directory Status");
586                                 OUT_FS_AFSVolSync();
587                                 break;
588                         case 143: /* old set lock */
589                         case 144: /* old extend lock */
590                         case 145: /* old release lock */
591                         case 147: /* give up callbacks */
592                         case 150: /* set volume status */
593                         case 152: /* check token */
594                                 /* nothing returned */
595                                 break;
596                         case 146: /* get statistics */
597                                 OUT_FS_ViceStatistics();
598                                 break;
599                         case 148: /* get volume info */
600                         case 154: /* n-get-volume-info */
601                                 OUT_FS_VolumeInfo();
602                                 break;
603                         case 149: /* get volume status */
604                                 OUT_FS_AFSFetchVolumeStatus();
605                                 OUT_RXString(hf_afs_fs_volname);
606                                 OUT_RXString(hf_afs_fs_offlinemsg);
607                                 OUT_RXString(hf_afs_fs_motd);
608                                 break;
609                         case 151: /* root volume */
610                                 OUT_RXString(hf_afs_fs_volname);
611                                 break;
612                         case 153: /* get time */
613                                 OUT_TIMESTAMP(hf_afs_fs_timestamp);
614                                 break;
615                         case 155: /* bulk status */
616                                 OUT_FS_AFSBulkStats();
617                                 SKIP(4);
618                                 OUT_FS_AFSCBs();
619                                 OUT_FS_AFSVolSync();
620                                 break;
621                         case 156: /* set lock */
622                         case 157: /* extend lock */
623                         case 158: /* release lock */
624                                 OUT_FS_AFSVolSync();
625                                 break;
626                         case 159: /* x-stats-version */
627                                 OUT_UINT(hf_afs_fs_xstats_version);
628                                 break;
629                         case 160: /* get xstats */
630                                 OUT_UINT(hf_afs_fs_xstats_version);
631                                 OUT_TIMESECS(hf_afs_fs_xstats_timestamp);
632                                 OUT_FS_AFS_CollData();
633                                 break;
634                         case 162: /* flush cps */
635                                 OUT_UINT(hf_afs_fs_cps_spare2);
636                                 OUT_UINT(hf_afs_fs_cps_spare3);
637                                 break;
638                 }
639         }
640         else if ( rxinfo->type == RX_PACKET_TYPE_ABORT )
641         {
642                 OUT_UINT(hf_afs_fs_errcode);
643         }
644 }
645
646 static void
647 dissect_fs_request(tvbuff_t *tvb, struct rxinfo *rxinfo, proto_tree *tree, int offset, int opcode)
648 {
649         /* skip the opcode if this is the first packet in the stream */
650         if ( rxinfo->seq == 1 )
651         {
652                 offset += 4;  /* skip the opcode */
653         }
654
655         switch ( opcode )
656         {
657                 case 130: /* Fetch data */
658                         OUT_FS_AFSFid("Source");
659                         OUT_UINT(hf_afs_fs_offset);
660                         OUT_UINT(hf_afs_fs_length);
661                         break;
662                 case 131: /* Fetch ACL */
663                         OUT_FS_AFSFid("Target");
664                         break;
665                 case 132: /* Fetch Status */
666                         OUT_FS_AFSFid("Target");
667                         break;
668                 case 133: /* Store Data */
669                         if ( rxinfo->seq == 1 )
670                         {
671                                 OUT_FS_AFSFid("Destination");
672                                 OUT_FS_AFSStoreStatus("Status");
673                                 OUT_UINT(hf_afs_fs_offset);
674                                 OUT_UINT(hf_afs_fs_length);
675                                 OUT_UINT(hf_afs_fs_flength);
676                         }
677                         OUT_BYTES_ALL(hf_afs_fs_data);
678                         break;
679                 case 134: /* Store ACL */
680                         OUT_FS_AFSFid("Target");
681                         offset = dissect_acl(tvb, rxinfo, tree, offset);
682                         break;
683                 case 135: /* Store Status */
684                         OUT_FS_AFSFid("Target");
685                         OUT_FS_AFSStoreStatus("Status");
686                         break;
687                 case 136: /* Remove File */
688                         OUT_FS_AFSFid("Remove File");
689                         OUT_RXString(hf_afs_fs_name);
690                         break;
691                 case 137: /* Create File */
692                         OUT_FS_AFSFid("Target");
693                         OUT_RXString(hf_afs_fs_name);
694                         OUT_FS_AFSStoreStatus("Status");
695                         break;
696                 case 138: /* Rename file */
697                         OUT_FS_AFSFid("Old");
698                         OUT_RXString(hf_afs_fs_oldname);
699                         OUT_FS_AFSFid("New");
700                         OUT_RXString(hf_afs_fs_newname);
701                         break;
702                 case 139: /* Symlink */
703                         OUT_FS_AFSFid("File");
704                         OUT_RXString(hf_afs_fs_symlink_name);
705                         OUT_RXString(hf_afs_fs_symlink_content);
706                         OUT_FS_AFSStoreStatus("Status");
707                         break;
708                 case 140: /* Link */
709                         OUT_FS_AFSFid("Link To (New File)");
710                         OUT_RXString(hf_afs_fs_name);
711                         OUT_FS_AFSFid("Link From (Old File)");
712                         break;
713                 case 141: /* Make dir */
714                         OUT_FS_AFSFid("Target");
715                         OUT_RXString(hf_afs_fs_name);
716                         OUT_FS_AFSStoreStatus("Status");
717                         break;
718                 case 142: /* Remove dir */
719                         OUT_FS_AFSFid("Target");
720                         OUT_RXString(hf_afs_fs_name);
721                         break;
722                 case 143: /* Old Set Lock */
723                         OUT_FS_AFSFid("Target");
724                         OUT_UINT(hf_afs_fs_vicelocktype);
725                         OUT_FS_AFSVolSync();
726                         break;
727                 case 144: /* Old Extend Lock */
728                         OUT_FS_AFSFid("Target");
729                         OUT_FS_AFSVolSync();
730                         break;
731                 case 145: /* Old Release Lock */
732                         OUT_FS_AFSFid("Target");
733                         OUT_FS_AFSVolSync();
734                         break;
735                 case 146: /* Get statistics */
736                         /* no params */
737                         break;
738                 case 147: /* Give up callbacks */
739                         OUT_FS_AFSCBFids();
740                         OUT_FS_AFSCBs();
741                         break;
742                 case 148: /* Get vol info */
743                         OUT_RXString(hf_afs_fs_volname);
744                         break;
745                 case 149: /* Get vol stats */
746                         OUT_UINT(hf_afs_fs_volid);
747                         break;
748                 case 150: /* Set vol stats */
749                         OUT_UINT(hf_afs_fs_volid);
750                         OUT_FS_AFSStoreVolumeStatus();
751                         OUT_RXString(hf_afs_fs_volname);
752                         OUT_RXString(hf_afs_fs_offlinemsg);
753                         OUT_RXString(hf_afs_fs_motd);
754                         break;
755                 case 151: /* get root volume */
756                         /* no params */
757                         break;
758                 case 152: /* check token */
759                         OUT_UINT(hf_afs_fs_viceid);
760                         OUT_FS_AFSTOKEN();
761                         break;
762                 case 153: /* get time */
763                         /* no params */
764                         break;
765                 case 154: /* new get vol info */
766                         OUT_RXString(hf_afs_fs_volname);
767                         break;
768                 case 155: /* bulk stat */
769                         OUT_FS_AFSCBFids();
770                         break;
771                 case 156: /* Set Lock */
772                         OUT_FS_AFSFid("Target");
773                         OUT_UINT(hf_afs_fs_vicelocktype);
774                         break;
775                 case 157: /* Extend Lock */
776                         OUT_FS_AFSFid("Target");
777                         break;
778                 case 158: /* Release Lock */
779                         OUT_FS_AFSFid("Target");
780                         break;
781                 case 159: /* xstats version */
782                         /* no params */
783                         break;
784                 case 160: /* get xstats */
785                         OUT_UINT(hf_afs_fs_xstats_clientversion);
786                         OUT_UINT(hf_afs_fs_xstats_collnumber);
787                         break;
788                 case 161: /* lookup */
789                         OUT_FS_AFSFid("Target");
790                         OUT_RXString(hf_afs_fs_name);
791                         break;
792                 case 162: /* flush cps */
793                         OUT_FS_ViceIds();
794                         OUT_FS_IPAddrs();
795                         OUT_UINT(hf_afs_fs_cps_spare1);
796                         break;
797                 case 163: /* dfs symlink */
798                         OUT_FS_AFSFid("Target");
799                         OUT_RXString(hf_afs_fs_symlink_name);
800                         OUT_RXString(hf_afs_fs_symlink_content);
801                         OUT_FS_AFSStoreStatus("Symlink Status");
802                         break;
803         }
804 }
805
806 /*
807  * BOS Helpers
808  */
809 static void
810 dissect_bos_reply(tvbuff_t *tvb, struct rxinfo *rxinfo, proto_tree *tree, int offset, int opcode)
811 {
812         if ( rxinfo->type == RX_PACKET_TYPE_DATA )
813         {
814                 switch ( opcode )
815                 {
816                         case 80: /* create bnode */
817                                 /* no output */
818                                 break;
819                         case 81: /* delete bnode */
820                                 /* no output */
821                                 break;
822                         case 82: /* set status */
823                                 /* no output */
824                                 break;
825                         case 83: /* get status */
826                                 OUT_INT(hf_afs_bos_status);
827                                 OUT_RXString(hf_afs_bos_statusdesc);
828                                 break;
829                         case 84: /* enumerate instance */
830                                 OUT_RXString(hf_afs_bos_instance);
831                                 break;
832                         case 85: /* get instance info */
833                                 OUT_RXString(hf_afs_bos_type);
834                                 OUT_BOS_STATUS();
835                                 break;
836                         case 86: /* get instance parm */
837                                 OUT_RXString(hf_afs_bos_parm);
838                                 break;
839                         case 87: /* add siperuser */
840                                 /* no output */
841                                 break;
842                         case 88: /* delete superuser */
843                                 /* no output */
844                                 break;
845                         case 89: /* list superusers */
846                                 OUT_RXString(hf_afs_bos_user);
847                                 break;
848                         case 90: /* list keys */
849                                 OUT_UINT(hf_afs_bos_kvno);
850                                 OUT_BOS_KEY();
851                                 OUT_BOS_KEYINFO();
852                                 break;
853                         case 91: /* add key */
854                                 /* no output */
855                                 break;
856                         case 92: /* delete key */
857                                 /* no output */
858                                 break;
859                         case 93: /* set cell name */
860                                 /* no output */
861                                 break;
862                         case 94: /* get cell name */
863                                 OUT_RXString(hf_afs_bos_cell);
864                                 break;
865                         case 95: /* get cell host */
866                                 OUT_RXString(hf_afs_bos_host);
867                                 break;
868                         case 96: /* add cell host */
869                                 /* no output */
870                                 break;
871                         case 97: /* delete cell host */
872                                 /* no output */
873                                 break;
874                         case 98: /* set tstatus */
875                                 /* no output */
876                                 break;
877                         case 99: /* shutdown all */
878                                 /* no output */
879                                 break;
880                         case 100: /* restart all */
881                                 /* no output */
882                                 break;
883                         case 101: /* startup all */
884                                 /* no output */
885                                 break;
886                         case 102: /* set noauth flag */
887                                 /* no output */
888                                 break;
889                         case 103: /* rebozo */
890                                 /* no output */
891                                 break;
892                         case 104: /* restart */
893                                 /* no output */
894                                 break;
895                         case 105: /* install */
896                                 /* no output */
897                                 break;
898                         case 106: /* uninstall */
899                                 /* no output */
900                                 break;
901                         case 107: /* get dates */
902                                 OUT_TIMESECS(hf_afs_bos_newtime);
903                                 OUT_TIMESECS(hf_afs_bos_baktime);
904                                 OUT_TIMESECS(hf_afs_bos_oldtime);
905                                 break;
906                         case 108: /* exec */
907                                 /* no output */
908                                 break;
909                         case 109: /* prune */
910                                 /* no output */
911                                 break;
912                         case 110: /* set restart time */
913                                 /* no output */
914                                 break;
915                         case 111: /* get restart time */
916                                 OUT_BOS_TIME();
917                                 break;
918                         case 112: /* get log */
919                                 /* need to make this dump a big string somehow */
920                                 OUT_BYTES_ALL(hf_afs_bos_data);
921                                 break;
922                         case 113: /* wait all */
923                                 /* no output */
924                                 break;
925                         case 114: /* get instance strings */
926                                 OUT_RXString(hf_afs_bos_error);
927                                 OUT_RXString(hf_afs_bos_spare1);
928                                 OUT_RXString(hf_afs_bos_spare2);
929                                 OUT_RXString(hf_afs_bos_spare3);
930                                 break;
931                 }
932         }
933         else if ( rxinfo->type == RX_PACKET_TYPE_ABORT )
934         {
935                 OUT_UINT(hf_afs_bos_errcode);
936         }
937 }
938
939 static void
940 dissect_bos_request(tvbuff_t *tvb, struct rxinfo *rxinfo _U_, proto_tree *tree, int offset, int opcode)
941 {
942         offset += 4;  /* skip the opcode */
943
944         switch ( opcode )
945         {
946                 case 80: /* create b node */
947                         OUT_RXString(hf_afs_bos_type);
948                         OUT_RXString(hf_afs_bos_instance);
949                         OUT_RXString(hf_afs_bos_parm);
950                         OUT_RXString(hf_afs_bos_parm);
951                         OUT_RXString(hf_afs_bos_parm);
952                         OUT_RXString(hf_afs_bos_parm);
953                         OUT_RXString(hf_afs_bos_parm);
954                         OUT_RXString(hf_afs_bos_parm);
955                         break;
956                 case 81: /* delete b node */
957                         OUT_RXString(hf_afs_bos_instance);
958                         break;
959                 case 82: /* set status */
960                         OUT_RXString(hf_afs_bos_instance);
961                         OUT_INT(hf_afs_bos_status);
962                         break;
963                 case 83: /* get status */
964                         OUT_RXString(hf_afs_bos_instance);
965                         break;
966                 case 84: /* enumerate instance */
967                         OUT_UINT(hf_afs_bos_num);
968                         break;
969                 case 85: /* get instance info */
970                         OUT_RXString(hf_afs_bos_instance);
971                         break;
972                 case 86: /* get instance parm */
973                         OUT_RXString(hf_afs_bos_instance);
974                         OUT_UINT(hf_afs_bos_num);
975                         break;
976                 case 87: /* add super user */
977                         OUT_RXString(hf_afs_bos_user);
978                         break;
979                 case 88: /* delete super user */
980                         OUT_RXString(hf_afs_bos_user);
981                         break;
982                 case 89: /* list super users */
983                         OUT_UINT(hf_afs_bos_num);
984                         break;
985                 case 90: /* list keys */
986                         OUT_UINT(hf_afs_bos_num);
987                         break;
988                 case 91: /* add key */
989                         OUT_UINT(hf_afs_bos_num);
990                         OUT_BOS_KEY();
991                         break;
992                 case 92: /* delete key */
993                         OUT_UINT(hf_afs_bos_num);
994                         break;
995                 case 93: /* set cell name */
996                         OUT_RXString(hf_afs_bos_content);
997                         break;
998                 case 95: /* set cell host */
999                         OUT_UINT(hf_afs_bos_num);
1000                         break;
1001                 case 96: /* add cell host */
1002                         OUT_RXString(hf_afs_bos_content);
1003                         break;
1004                 case 97: /* delete cell host */
1005                         OUT_RXString(hf_afs_bos_content);
1006                         break;
1007                 case 98: /* set t status */
1008                         OUT_RXString(hf_afs_bos_content);
1009                         OUT_INT(hf_afs_bos_status);
1010                         break;
1011                 case 99: /* shutdown all */
1012                         /* no params */
1013                         break;
1014                 case 100: /* restart all */
1015                         /* no params */
1016                         break;
1017                 case 101: /* startup all */
1018                         /* no params */
1019                         break;
1020                 case 102: /* set no-auth flag */
1021                         OUT_UINT(hf_afs_bos_flags);
1022                         break;
1023                 case 103: /* re-bozo? */
1024                         /* no params */
1025                         break;
1026                 case 104: /* restart */
1027                         OUT_RXString(hf_afs_bos_instance);
1028                         break;
1029                 case 105: /* install */
1030                         OUT_RXString(hf_afs_bos_path);
1031                         OUT_UINT(hf_afs_bos_size);
1032                         OUT_UINT(hf_afs_bos_flags);
1033                         OUT_UINT(hf_afs_bos_date);
1034                         break;
1035                 case 106: /* uninstall */
1036                         OUT_RXString(hf_afs_bos_path);
1037                         break;
1038                 case 107: /* get dates */
1039                         OUT_RXString(hf_afs_bos_path);
1040                         break;
1041                 case 108: /* exec */
1042                         OUT_RXString(hf_afs_bos_cmd);
1043                         break;
1044                 case 109: /* prune */
1045                         OUT_UINT(hf_afs_bos_flags);
1046                         break;
1047                 case 110: /* set restart time */
1048                         OUT_UINT(hf_afs_bos_num);
1049                         OUT_BOS_TIME();
1050                         break;
1051                 case 111: /* get restart time */
1052                         OUT_UINT(hf_afs_bos_num);
1053                         break;
1054                 case 112: /* get log */
1055                         OUT_RXString(hf_afs_bos_file);
1056                         break;
1057                 case 113: /* wait all */
1058                         /* no params */
1059                         break;
1060                 case 114: /* get instance strings */
1061                         OUT_RXString(hf_afs_bos_content);
1062                         break;
1063         }
1064 }
1065
1066 /*
1067  * VOL Helpers
1068  */
1069 static void
1070 dissect_vol_reply(tvbuff_t *tvb, struct rxinfo *rxinfo, proto_tree *tree, int offset, int opcode)
1071 {
1072         if ( rxinfo->type == RX_PACKET_TYPE_DATA )
1073         {
1074                 switch ( opcode )
1075                 {
1076                         case 121:
1077                                 /* should loop here maybe */
1078                                 OUT_UINT(hf_afs_vol_count);
1079                                 OUT_RXStringV(hf_afs_vol_name, 32); /* not sure on  */
1080                                 break;
1081                 }
1082         }
1083         else if ( rxinfo->type == RX_PACKET_TYPE_ABORT )
1084         {
1085                 OUT_UINT(hf_afs_vol_errcode);
1086         }
1087 }
1088
1089 static void
1090 dissect_vol_request(tvbuff_t *tvb, struct rxinfo *rxinfo _U_, proto_tree *tree, int offset, int opcode)
1091 {
1092         offset += 4;  /* skip the opcode */
1093
1094         switch ( opcode )
1095         {
1096                 case 121: /* list one vol */
1097                         OUT_UINT(hf_afs_vol_count);
1098                         OUT_UINT(hf_afs_vol_id);
1099                         break;
1100         }
1101 }
1102
1103 /*
1104  * KAUTH Helpers
1105  */
1106 static void
1107 dissect_kauth_reply(tvbuff_t *tvb, struct rxinfo *rxinfo, proto_tree *tree, int offset, int opcode)
1108 {
1109         if ( rxinfo->type == RX_PACKET_TYPE_DATA )
1110         {
1111                 switch ( opcode )
1112                 {
1113                 }
1114         }
1115         else if ( rxinfo->type == RX_PACKET_TYPE_ABORT )
1116         {
1117                 OUT_UINT(hf_afs_kauth_errcode);
1118         }
1119 }
1120
1121 static void
1122 dissect_kauth_request(tvbuff_t *tvb, struct rxinfo *rxinfo _U_, proto_tree *tree, int offset, int opcode)
1123 {
1124         offset += 4;  /* skip the opcode */
1125
1126         switch ( opcode )
1127         {
1128                 case 1: /* authenticate old */
1129                 case 21: /* authenticate */
1130                 case 22: /* authenticate v2 */
1131                 case 2: /* change pw */
1132                 case 5: /* set fields */
1133                 case 6: /* create user */
1134                 case 7: /* delete user */
1135                 case 8: /* get entry */
1136                 case 14: /* unlock */
1137                 case 15: /* lock status */
1138                         OUT_RXString(hf_afs_kauth_princ);
1139                         OUT_RXString(hf_afs_kauth_realm);
1140                         OUT_BYTES_ALL(hf_afs_kauth_data);
1141                         break;
1142                 case 3: /* getticket-old */
1143                 case 23: /* getticket */
1144                         OUT_KAUTH_GetTicket();
1145                         break;
1146                 case 4: /* set pass */
1147                         OUT_RXString(hf_afs_kauth_princ);
1148                         OUT_RXString(hf_afs_kauth_realm);
1149                         OUT_UINT(hf_afs_kauth_kvno);
1150                         break;
1151                 case 12: /* get pass */
1152                         OUT_RXString(hf_afs_kauth_name);
1153                         break;
1154         }
1155 }
1156
1157 /*
1158  * CB Helpers
1159  */
1160 static void
1161 dissect_cb_reply(tvbuff_t *tvb, struct rxinfo *rxinfo, proto_tree *tree, int offset, int opcode)
1162 {
1163         if ( rxinfo->type == RX_PACKET_TYPE_DATA )
1164         {
1165                 switch ( opcode )
1166                 {
1167                 }
1168         }
1169         else if ( rxinfo->type == RX_PACKET_TYPE_ABORT )
1170         {
1171                 OUT_UINT(hf_afs_cb_errcode);
1172         }
1173 }
1174
1175 static void
1176 dissect_cb_request(tvbuff_t *tvb, struct rxinfo *rxinfo _U_, proto_tree *tree, int offset, int opcode)
1177 {
1178         offset += 4;  /* skip the opcode */
1179
1180         switch ( opcode )
1181         {
1182                 case 204: /* callback */
1183                 {
1184                         unsigned int i,j;
1185
1186                         j = tvb_get_ntohl(tvb, offset);
1187                         offset += 4;
1188
1189                         for (i=0; i<j; i++)
1190                         {
1191                                 OUT_CB_AFSFid("Target");
1192                         }
1193
1194                         j = tvb_get_ntohl(tvb, offset);
1195                         offset += 4;
1196                         for (i=0; i<j; i++)
1197                         {
1198                                 OUT_CB_AFSCallBack();
1199                         }
1200                 }
1201         }
1202 }
1203
1204 /*
1205  * PROT Helpers
1206  */
1207 static void
1208 dissect_prot_reply(tvbuff_t *tvb, struct rxinfo *rxinfo, proto_tree *tree, int offset, int opcode)
1209 {
1210         if ( rxinfo->type == RX_PACKET_TYPE_DATA )
1211         {
1212                 switch ( opcode )
1213                 {
1214                         case 504: /* name to id */
1215                                 {
1216                                         unsigned int i, j;
1217
1218                                         j = tvb_get_ntohl(tvb, offset);
1219                                         OUT_UINT(hf_afs_prot_count);
1220
1221                                         for (i=0; i<j; i++)
1222                                         {
1223                                                 OUT_UINT(hf_afs_prot_id);
1224                                         }
1225                                 }
1226                                 break;
1227                         case 505: /* id to name */
1228                                 {
1229                                         unsigned int i, j;
1230
1231                                         j = tvb_get_ntohl(tvb, offset);
1232                                         OUT_UINT(hf_afs_prot_count);
1233
1234                                         for (i=0; i<j; i++)
1235                                         {
1236                                                 OUT_RXStringV(hf_afs_prot_name, PRNAMEMAX);
1237                                         }
1238                                 }
1239                                 break;
1240                         case 508: /* get cps */
1241                         case 514: /* list elements */
1242                         case 517: /* list owned */
1243                         case 518: /* get cps2 */
1244                         case 519: /* get host cps */
1245                                 {
1246                                         unsigned int i, j;
1247
1248                                         j = tvb_get_ntohl(tvb, offset);
1249                                         OUT_UINT(hf_afs_prot_count);
1250
1251                                         for (i=0; i<j; i++)
1252                                         {
1253                                                 OUT_UINT(hf_afs_prot_id);
1254                                         }
1255                                 }
1256                                 break;
1257                         case 510: /* list max */
1258                                 OUT_UINT(hf_afs_prot_maxuid);
1259                                 OUT_UINT(hf_afs_prot_maxgid);
1260                                 break;
1261                 }
1262         }
1263         else if ( rxinfo->type == RX_PACKET_TYPE_ABORT )
1264         {
1265                 OUT_UINT(hf_afs_prot_errcode);
1266         }
1267 }
1268
1269 static void
1270 dissect_prot_request(tvbuff_t *tvb, struct rxinfo *rxinfo _U_, proto_tree *tree, int offset, int opcode)
1271 {
1272         offset += 4;  /* skip the opcode */
1273
1274         switch ( opcode )
1275         {
1276                 case 500: /* new user */
1277                         OUT_RXString(hf_afs_prot_name);
1278                         OUT_UINT(hf_afs_prot_id);
1279                         OUT_UINT(hf_afs_prot_oldid);
1280                         break;
1281                 case 501: /* where is it */
1282                 case 506: /* delete */
1283                 case 508: /* get cps */
1284                 case 512: /* list entry */
1285                 case 514: /* list elements */
1286                 case 517: /* list owned */
1287                 case 519: /* get host cps */
1288                         OUT_UINT(hf_afs_prot_id);
1289                         break;
1290                 case 502: /* dump entry */
1291                         OUT_UINT(hf_afs_prot_pos);
1292                         break;
1293                 case 503: /* add to group */
1294                 case 507: /* remove from group */
1295                 case 515: /* is a member of? */
1296                         OUT_UINT(hf_afs_prot_uid);
1297                         OUT_UINT(hf_afs_prot_gid);
1298                         break;
1299                 case 504: /* name to id */
1300                         {
1301                                 unsigned int i, j;
1302
1303                                 j = tvb_get_ntohl(tvb, offset);
1304                                 OUT_UINT(hf_afs_prot_count);
1305
1306                                 for (i=0; i<j; i++)
1307                                 {
1308                                         OUT_RXStringV(hf_afs_prot_name,PRNAMEMAX);
1309                                 }
1310                         }
1311                         break;
1312                 case 505: /* id to name */
1313                         {
1314                                 unsigned int i, j;
1315
1316                                 j = tvb_get_ntohl(tvb, offset);
1317                                 OUT_UINT(hf_afs_prot_count);
1318
1319                                 for (i=0; i<j; i++)
1320                                 {
1321                                         OUT_UINT(hf_afs_prot_id);
1322                                 }
1323                         }
1324                         break;
1325                 case 509: /* new entry */
1326                         OUT_RXString(hf_afs_prot_name);
1327                         OUT_UINT(hf_afs_prot_flag);
1328                         OUT_UINT(hf_afs_prot_oldid);
1329                         break;
1330                 case 511: /* set max */
1331                         OUT_UINT(hf_afs_prot_id);
1332                         OUT_UINT(hf_afs_prot_flag);
1333                         break;
1334                 case 513: /* change entry */
1335                         OUT_UINT(hf_afs_prot_id);
1336                         OUT_RXString(hf_afs_prot_name);
1337                         OUT_UINT(hf_afs_prot_oldid);
1338                         OUT_UINT(hf_afs_prot_newid);
1339                         break;
1340                 case 520: /* update entry */
1341                         OUT_UINT(hf_afs_prot_id);
1342                         OUT_RXString(hf_afs_prot_name);
1343                         break;
1344         }
1345 }
1346
1347 /*
1348  * VLDB Helpers
1349  */
1350 static void
1351 dissect_vldb_reply(tvbuff_t *tvb, struct rxinfo *rxinfo, proto_tree *tree, int offset, int opcode)
1352 {
1353         if ( rxinfo->type == RX_PACKET_TYPE_DATA )
1354         {
1355                 switch ( opcode )
1356                 {
1357                         case 510: /* list entry */
1358                                 OUT_UINT(hf_afs_vldb_count);
1359                                 OUT_UINT(hf_afs_vldb_nextindex);
1360                                 break;
1361                         case 503: /* get entry by id */
1362                         case 504: /* get entry by name */
1363                                 {
1364                                         int nservers,i,j;
1365                                         OUT_RXStringV(hf_afs_vldb_name, VLNAMEMAX);
1366                                         SKIP(4);
1367                                         nservers = tvb_get_ntohl(tvb, offset);
1368                                         OUT_UINT(hf_afs_vldb_numservers);
1369                                         for (i=0; i<8; i++)
1370                                         {
1371                                                 if ( i<nservers )
1372                                                 {
1373                                                         OUT_IP(hf_afs_vldb_server);
1374                                                 }
1375                                                 else
1376                                                 {
1377                                                         SKIP(4);
1378                                                 }
1379                                         }
1380                                         for (i=0; i<8; i++)
1381                                         {
1382                                                 char part[8];
1383                                                 j = tvb_get_ntohl(tvb, offset);
1384                                                 strcpy(part, "/vicepa");
1385                                                 if ( i<nservers && j<=25 )
1386                                                 {
1387                                                         part[6] = 'a' + (char) j;
1388                                                         proto_tree_add_string(tree, hf_afs_vldb_partition, tvb,
1389                                                                 offset, 4, part);
1390                                                 }
1391                                                 SKIP(4);
1392                                         }
1393                                         SKIP(8 * sizeof(guint32));
1394                                         OUT_UINT(hf_afs_vldb_rwvol);
1395                                         OUT_UINT(hf_afs_vldb_rovol);
1396                                         OUT_UINT(hf_afs_vldb_bkvol);
1397                                         OUT_UINT(hf_afs_vldb_clonevol);
1398                                         OUT_VLDB_Flags();
1399                                 }
1400                                 break;
1401                         case 505: /* get new volume id */
1402                                 OUT_UINT(hf_afs_vldb_id);
1403                                 break;
1404                         case 521: /* list entry */
1405                         case 529: /* list entry U */
1406                                 OUT_UINT(hf_afs_vldb_count);
1407                                 OUT_UINT(hf_afs_vldb_nextindex);
1408                                 break;
1409                         case 518: /* get entry by id n */
1410                         case 519: /* get entry by name N */
1411                                 {
1412                                         int nservers,i,j;
1413                                         OUT_RXStringV(hf_afs_vldb_name, VLNAMEMAX);
1414                                         nservers = tvb_get_ntohl(tvb, offset);
1415                                         OUT_UINT(hf_afs_vldb_numservers);
1416                                         for (i=0; i<13; i++)
1417                                         {
1418                                                 if ( i<nservers )
1419                                                 {
1420                                                         OUT_IP(hf_afs_vldb_server);
1421                                                 }
1422                                                 else
1423                                                 {
1424                                                         SKIP(4);
1425                                                 }
1426                                         }
1427                                         for (i=0; i<13; i++)
1428                                         {
1429                                                 char part[8];
1430                                                 j = tvb_get_ntohl(tvb, offset);
1431                                                 strcpy(part, "/vicepa");
1432                                                 if ( i<nservers && j<=25 )
1433                                                 {
1434                                                         part[6] = 'a' + (char) j;
1435                                                         proto_tree_add_string(tree, hf_afs_vldb_partition, tvb,
1436                                                                 offset, 4, part);
1437                                                 }
1438                                                 SKIP(4);
1439                                         }
1440                                         SKIP(13 * sizeof(guint32));
1441                                         OUT_UINT(hf_afs_vldb_rwvol);
1442                                         OUT_UINT(hf_afs_vldb_rovol);
1443                                         OUT_UINT(hf_afs_vldb_bkvol);
1444                                 }
1445                                 break;
1446                         case 526: /* get entry by id u */
1447                         case 527: /* get entry by name u */
1448                                 {
1449                                         int nservers,i,j;
1450                                         OUT_RXStringV(hf_afs_vldb_name, VLNAMEMAX);
1451                                         nservers = tvb_get_ntohl(tvb, offset);
1452                                         OUT_UINT(hf_afs_vldb_numservers);
1453                                         for (i=0; i<13; i++)
1454                                         {
1455                                                 if ( i<nservers )
1456                                                 {
1457                                                         OUT_UUID(hf_afs_vldb_serveruuid);
1458                                                 }
1459                                                 else
1460                                                 {
1461                                                         SKIP_UUID();
1462                                                 }
1463                                         }
1464                                         for (i=0; i<13; i++)
1465                                         {
1466                                                 if ( i<nservers )
1467                                                 {
1468                                                         OUT_UINT(hf_afs_vldb_serveruniq);
1469                                                 }
1470                                                 else
1471                                                 {
1472                                                         SKIP(sizeof(guint32));
1473                                                 }
1474                                         }
1475                                         for (i=0; i<13; i++)
1476                                         {
1477                                                 char part[8];
1478                                                 j = tvb_get_ntohl(tvb, offset);
1479                                                 strcpy(part, "/vicepa");
1480                                                 if ( i<nservers && j<=25 )
1481                                                 {
1482                                                         part[6] = 'a' + (char) j;
1483                                                         proto_tree_add_string(tree, hf_afs_vldb_partition, tvb,
1484                                                                 offset, 4, part);
1485                                                 }
1486                                                 SKIP(4);
1487                                         }
1488                                         for (i=0; i<13; i++)
1489                                         {
1490                                                 if ( i<nservers )
1491                                                 {
1492                                                         OUT_UINT(hf_afs_vldb_serverflags);
1493                                                 }
1494                                                 else
1495                                                 {
1496                                                         SKIP(sizeof(guint32));
1497                                                 }
1498                                         }
1499                                         OUT_UINT(hf_afs_vldb_rwvol);
1500                                         OUT_UINT(hf_afs_vldb_rovol);
1501                                         OUT_UINT(hf_afs_vldb_bkvol);
1502                                         OUT_UINT(hf_afs_vldb_clonevol);
1503                                         OUT_UINT(hf_afs_vldb_flags);
1504                                         OUT_UINT(hf_afs_vldb_spare1);
1505                                         OUT_UINT(hf_afs_vldb_spare2);
1506                                         OUT_UINT(hf_afs_vldb_spare3);
1507                                         OUT_UINT(hf_afs_vldb_spare4);
1508                                         OUT_UINT(hf_afs_vldb_spare5);
1509                                         OUT_UINT(hf_afs_vldb_spare6);
1510                                         OUT_UINT(hf_afs_vldb_spare7);
1511                                         OUT_UINT(hf_afs_vldb_spare8);
1512                                         OUT_UINT(hf_afs_vldb_spare9);
1513                                 }
1514                                 break;
1515                 }
1516         }
1517         else if ( rxinfo->type == RX_PACKET_TYPE_ABORT )
1518         {
1519                 OUT_UINT(hf_afs_vldb_errcode);
1520         }
1521 }
1522
1523 static void
1524 dissect_vldb_request(tvbuff_t *tvb, struct rxinfo *rxinfo _U_, proto_tree *tree, int offset, int opcode)
1525 {
1526         offset += 4;  /* skip the opcode */
1527
1528         switch ( opcode )
1529         {
1530                 case 501: /* create new volume */
1531                 case 517: /* create entry N */
1532                         OUT_RXStringV(hf_afs_vldb_name, VLNAMEMAX);
1533                         break;
1534                 case 502: /* delete entry */
1535                 case 503: /* get entry by id */
1536                 case 507: /* update entry */
1537                 case 508: /* set lock */
1538                 case 509: /* release lock */
1539                 case 518: /* get entry by id */
1540                         OUT_UINT(hf_afs_vldb_id);
1541                         OUT_UINT(hf_afs_vldb_type);
1542                         break;
1543                 case 504: /* get entry by name */
1544                 case 519: /* get entry by name N */
1545                 case 524: /* update entry by name */
1546                 case 527: /* get entry by name U */
1547                         OUT_RXString(hf_afs_vldb_name);
1548                         break;
1549                 case 505: /* get new vol id */
1550                         OUT_UINT(hf_afs_vldb_bump);
1551                         break;
1552                 case 506: /* replace entry */
1553                 case 520: /* replace entry N */
1554                         OUT_UINT(hf_afs_vldb_id);
1555                         OUT_UINT(hf_afs_vldb_type);
1556                         OUT_RXStringV(hf_afs_vldb_name, VLNAMEMAX);
1557                         break;
1558                 case 510: /* list entry */
1559                 case 521: /* list entry N */
1560                         OUT_UINT(hf_afs_vldb_index);
1561                         break;
1562                 case 532: /* regaddr */
1563                         OUT_UUID(hf_afs_vldb_serveruuid);
1564                         OUT_UINT(hf_afs_vldb_spare1);
1565                         OUT_VLDB_BulkAddr();
1566                         break;
1567         }
1568 }
1569
1570 /*
1571  * UBIK Helpers
1572  */
1573 static void
1574 dissect_ubik_reply(tvbuff_t *tvb, struct rxinfo *rxinfo _U_, proto_tree *tree, int offset, int opcode)
1575 {
1576         switch ( opcode )
1577         {
1578                 case 10000: /* vote-beacon */
1579                         break;
1580                 case 10001: /* vote-debug-old */
1581                         OUT_UBIK_DebugOld();
1582                         break;
1583                 case 10002: /* vote-sdebug-old */
1584                         OUT_UBIK_SDebugOld();
1585                         break;
1586                 case 10003: /* vote-get syncsite */
1587                         break;
1588                 case 10004: /* vote-debug */
1589                         OUT_UBIK_DebugOld();
1590                         OUT_UBIK_InterfaceAddrs();
1591                         break;
1592                 case 10005: /* vote-sdebug */
1593                         OUT_UBIK_SDebugOld();
1594                         OUT_UBIK_InterfaceAddrs();
1595                         break;
1596                 case 10006: /* vote-xdebug */
1597                         OUT_UBIK_DebugOld();
1598                         OUT_UBIK_InterfaceAddrs();
1599                         OUT_UINT(hf_afs_ubik_isclone);
1600                         break;
1601                 case 10007: /* vote-xsdebug */
1602                         OUT_UBIK_SDebugOld();
1603                         OUT_UBIK_InterfaceAddrs();
1604                         OUT_UINT(hf_afs_ubik_isclone);
1605                         break;
1606                 case 20000: /* disk-begin */
1607                         break;
1608                 case 20004: /* get version */
1609                         OUT_UBIKVERSION("DB Version");
1610                         break;
1611                 case 20010: /* disk-probe */
1612                         break;
1613                 case 20012: /* disk-interfaceaddr */
1614                         OUT_UBIK_InterfaceAddrs();
1615                         break;
1616         }
1617 }
1618
1619 static void
1620 dissect_ubik_request(tvbuff_t *tvb, struct rxinfo *rxinfo _U_, proto_tree *tree, int offset, int opcode)
1621 {
1622         offset += 4;  /* skip the opcode */
1623
1624         switch ( opcode )
1625         {
1626                 case 10000: /* vote-beacon */
1627                         OUT_UINT(hf_afs_ubik_state);
1628                         OUT_TIMESECS(hf_afs_ubik_votestart);
1629                         OUT_UBIKVERSION("DB Version");
1630                         OUT_UBIKVERSION("TID");
1631                         break;
1632                 case 10001: /* vote-debug-old */
1633                         break;
1634                 case 10002: /* vote-sdebug-old */
1635                         OUT_UINT(hf_afs_ubik_site);
1636                         break;
1637                 case 10003: /* vote-get sync site */
1638                         OUT_IP(hf_afs_ubik_site);
1639                         break;
1640                 case 10004: /* vote-debug */
1641                 case 10005: /* vote-sdebug */
1642                         OUT_IP(hf_afs_ubik_site);
1643                         break;
1644                 case 20000: /* disk-begin */
1645                         OUT_UBIKVERSION("TID");
1646                         break;
1647                 case 20001: /* disk-commit */
1648                         OUT_UBIKVERSION("TID");
1649                         break;
1650                 case 20002: /* disk-lock */
1651                         OUT_UBIKVERSION("TID");
1652                         OUT_UINT(hf_afs_ubik_file);
1653                         OUT_UINT(hf_afs_ubik_pos);
1654                         OUT_UINT(hf_afs_ubik_length);
1655                         OUT_UINT(hf_afs_ubik_locktype);
1656                         break;
1657                 case 20003: /* disk-write */
1658                         OUT_UBIKVERSION("TID");
1659                         OUT_UINT(hf_afs_ubik_file);
1660                         OUT_UINT(hf_afs_ubik_pos);
1661                         break;
1662                 case 20004: /* disk-get version */
1663                         break;
1664                 case 20005: /* disk-get file */
1665                         OUT_UINT(hf_afs_ubik_file);
1666                         break;
1667                 case 20006: /* disk-send file */
1668                         OUT_UINT(hf_afs_ubik_file);
1669                         OUT_UINT(hf_afs_ubik_length);
1670                         OUT_UBIKVERSION("DB Version");
1671                         break;
1672                 case 20007: /* disk-abort */
1673                 case 20008: /* disk-release locks */
1674                 case 20010: /* disk-probe */
1675                         break;
1676                 case 20009: /* disk-truncate */
1677                         OUT_UBIKVERSION("TID");
1678                         OUT_UINT(hf_afs_ubik_file);
1679                         OUT_UINT(hf_afs_ubik_length);
1680                         break;
1681                 case 20011: /* disk-writev */
1682                         OUT_UBIKVERSION("TID");
1683                         break;
1684                 case 20012: /* disk-interfaceaddr */
1685                         OUT_UBIK_InterfaceAddrs();
1686                         break;
1687                 case 20013: /* disk-set version */
1688                         OUT_UBIKVERSION("TID");
1689                         OUT_UBIKVERSION("Old DB Version");
1690                         OUT_UBIKVERSION("New DB Version");
1691                         break;
1692         }
1693 }
1694
1695 /*
1696  * BACKUP Helpers
1697  */
1698 static void
1699 dissect_backup_reply(tvbuff_t *tvb, struct rxinfo *rxinfo, proto_tree *tree, int offset, int opcode)
1700 {
1701         if ( rxinfo->type == RX_PACKET_TYPE_DATA )
1702         {
1703                 switch ( opcode )
1704                 {
1705                 }
1706         }
1707         else if ( rxinfo->type == RX_PACKET_TYPE_ABORT )
1708         {
1709                 OUT_UINT(hf_afs_backup_errcode);
1710         }
1711 }
1712
1713 static void
1714 dissect_backup_request(tvbuff_t *tvb _U_, struct rxinfo *rxinfo _U_, proto_tree *tree _U_, int offset, int opcode)
1715 {
1716         offset += 4;  /* skip the opcode */
1717
1718         switch ( opcode )
1719         {
1720         }
1721 }
1722
1723 /*
1724  * Registration code for registering the protocol and fields
1725  */
1726
1727 void
1728 proto_register_afs(void)
1729 {
1730         static hf_register_info hf[] = {
1731 #include "packet-afs-register-info.h"
1732         };
1733         static gint *ett[] = {
1734                 &ett_afs,
1735                 &ett_afs_op,
1736                 &ett_afs_acl,
1737                 &ett_afs_fid,
1738                 &ett_afs_callback,
1739                 &ett_afs_ubikver,
1740                 &ett_afs_status,
1741                 &ett_afs_status_mask,
1742                 &ett_afs_volsync,
1743                 &ett_afs_volumeinfo,
1744                 &ett_afs_vicestat,
1745                 &ett_afs_vldb_flags,
1746         };
1747
1748         proto_afs = proto_register_protocol("Andrew File System (AFS)",
1749             "AFS (RX)", "afs");
1750         proto_register_field_array(proto_afs, hf, array_length(hf));
1751         proto_register_subtree_array(ett, array_length(ett));
1752         register_init_routine(&afs_init_protocol);
1753
1754         register_dissector("afs", dissect_afs, proto_afs);
1755 }