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