From Ronnie Sahlberg:
[obnox/wireshark/wip.git] / packet-afs-macros.h
1 /* packet-afs-macros.h
2  * Helper macros 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-macros.h,v 1.13 2002/01/18 21:30:05 nneul 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
35
36 /*
37  * Macros for helper dissection routines
38  *
39  * The macros are here to save on coding. They assume that
40  * the current offset is in 'offset', and that the offset
41  * should be incremented after performing the macro's operation.
42  */
43
44
45 /* Output a unsigned integer, stored into field 'field'
46    Assumes it is in network byte order, converts to host before using */
47 #define OUT_UINT(field) \
48         proto_tree_add_uint(tree, field, tvb, offset, sizeof(guint32), tvb_get_ntohl(tvb, offset)); \
49         offset += 4;
50
51 /* Output a unsigned integer, stored into field 'field'
52    Assumes it is in network byte order, converts to host before using */
53 #define OUT_INT(field) \
54         proto_tree_add_int(tree, field, tvb, offset, sizeof(gint32), tvb_get_ntohl(tvb, offset)); \
55         offset += 4;
56         
57 /* Output a unsigned integer, stored into field 'field'
58    Assumes it is in network byte order, converts to host before using, 
59    Note - does not increment offset, so can be used repeatedly for bitfields */
60 #define DISP_UINT(field) \
61         proto_tree_add_uint(tree,field,tvb,offset,sizeof(guint32),tvb_get_ntohl(tvb, offset)); 
62
63 /* Output an IPv4 address, stored into field 'field' */
64 #define OUT_IP(field) \
65         proto_tree_add_ipv4(tree,field,tvb,offset,sizeof(gint32),\
66                 tvb_get_letohl(tvb, offset));\
67         offset += 4;
68
69 /* Output a UNIX seconds/microseconds timestamp, after converting to an
70    nstime_t */
71 #define OUT_TIMESTAMP(field) \
72         { nstime_t ts; \
73         ts.secs = tvb_get_ntohl(tvb, offset); \
74         ts.nsecs = tvb_get_ntohl(tvb, offset)*1000; \
75         proto_tree_add_time(tree,field, tvb,offset,2*sizeof(guint32),&ts); \
76         offset += 8; \
77         }
78
79 /* Output a UNIX seconds-only timestamp, after converting to an nstime_t */
80 #define OUT_DATE(field) \
81         { nstime_t ts; \
82         ts.secs = tvb_get_ntohl(tvb, offset); \
83         ts.nsecs = 0; \
84         proto_tree_add_time(tree,field, tvb,offset,sizeof(guint32),&ts); \
85         offset += 4; \
86         }
87
88 /* Output a callback */
89 #define OUT_FS_AFSCallBack() \
90         {       proto_tree *save, *ti; \
91                 ti = proto_tree_add_text(tree, tvb, offset, 3*4, "Callback"); \
92                 save = tree; \
93                 tree = proto_item_add_subtree(ti, ett_afs_callback); \
94                 OUT_UINT(hf_afs_fs_callback_version); \
95                 OUT_DATE(hf_afs_fs_callback_expires); \
96                 OUT_UINT(hf_afs_fs_callback_type); \
97                 tree = save; \
98         }
99
100 /* Output a callback */
101 #define OUT_CB_AFSCallBack() \
102         {       proto_tree *save, *ti; \
103                 ti = proto_tree_add_text(tree, tvb, offset, 3*4, "Callback"); \
104                 save = tree; \
105                 tree = proto_item_add_subtree(ti, ett_afs_callback); \
106                 OUT_UINT(hf_afs_cb_callback_version); \
107                 OUT_DATE(hf_afs_cb_callback_expires); \
108                 OUT_UINT(hf_afs_cb_callback_type); \
109                 tree = save; \
110         }
111
112
113 /* Output a File ID */
114 #define OUT_FS_AFSFid(label) \
115         {       proto_tree *save, *ti; \
116                 ti = proto_tree_add_text(tree, tvb, offset, 3*4, \
117                         "FileID (%s)", label); \
118                 save = tree; \
119                 tree = proto_item_add_subtree(ti, ett_afs_fid); \
120                 OUT_UINT(hf_afs_fs_fid_volume); \
121                 OUT_UINT(hf_afs_fs_fid_vnode); \
122                 OUT_UINT(hf_afs_fs_fid_uniqifier); \
123                 tree = save; \
124         }
125
126 /* Output a Status mask */
127 #define OUT_FS_STATUSMASK() \
128         {       proto_tree *save, *ti; \
129                 guint32 mask; \
130                 mask = tvb_get_ntohl(tvb, offset); \
131                 ti = proto_tree_add_uint(tree, hf_afs_fs_status_mask, tvb, offset, \
132                         sizeof(guint32), mask); \
133                 save = tree; \
134                 tree = proto_item_add_subtree(ti, ett_afs_status_mask); \
135                 proto_tree_add_uint(tree, hf_afs_fs_status_mask_setmodtime, \
136                         tvb,offset,sizeof(guint32), mask); \
137                 proto_tree_add_uint(tree, hf_afs_fs_status_mask_setowner, \
138                         tvb,offset,sizeof(guint32), mask); \
139                 proto_tree_add_uint(tree, hf_afs_fs_status_mask_setgroup, \
140                         tvb,offset,sizeof(guint32), mask); \
141                 proto_tree_add_uint(tree, hf_afs_fs_status_mask_setmode, \
142                         tvb,offset,sizeof(guint32), mask); \
143                 proto_tree_add_uint(tree, hf_afs_fs_status_mask_setsegsize, \
144                         tvb,offset,sizeof(guint32), mask); \
145                 proto_tree_add_uint(tree, hf_afs_fs_status_mask_fsync, \
146                         tvb,offset,sizeof(guint32), mask); \
147                 offset += 4; \
148                 tree = save; \
149         }
150
151 /* Output a File ID */
152 #define OUT_CB_AFSFid(label) \
153         {       proto_tree *save, *ti; \
154                 ti = proto_tree_add_text(tree, tvb, offset, 3*4, \
155                         "FileID (%s)", label); \
156                 save = tree; \
157                 tree = proto_item_add_subtree(ti, ett_afs_fid); \
158                 OUT_UINT(hf_afs_cb_fid_volume); \
159                 OUT_UINT(hf_afs_cb_fid_vnode); \
160                 OUT_UINT(hf_afs_cb_fid_uniqifier); \
161                 tree = save; \
162         }
163         
164 /* Output a StoreStatus */
165 #define OUT_FS_AFSStoreStatus(label) \
166         {       proto_tree *save, *ti; \
167                 ti = proto_tree_add_text(tree, tvb, offset, 6*4, \
168                         label); \
169                 save = tree; \
170                 tree = proto_item_add_subtree(ti, ett_afs_status); \
171                 OUT_FS_STATUSMASK(); \
172                 OUT_DATE(hf_afs_fs_status_clientmodtime); \
173                 OUT_UINT(hf_afs_fs_status_owner); \
174                 OUT_UINT(hf_afs_fs_status_group); \
175                 OUT_UINT(hf_afs_fs_status_mode); \
176                 OUT_UINT(hf_afs_fs_status_segsize); \
177                 tree = save; \
178         }
179
180 /* Output a FetchStatus */
181 #define OUT_FS_AFSFetchStatus(label) \
182         {       proto_tree *save, *ti; \
183                 ti = proto_tree_add_text(tree, tvb, offset, 21*4, \
184                         label); \
185                 save = tree; \
186                 tree = proto_item_add_subtree(ti, ett_afs_status); \
187                 OUT_UINT(hf_afs_fs_status_interfaceversion); \
188                 OUT_UINT(hf_afs_fs_status_filetype); \
189                 OUT_UINT(hf_afs_fs_status_linkcount); \
190                 OUT_UINT(hf_afs_fs_status_length); \
191                 OUT_UINT(hf_afs_fs_status_dataversion); \
192                 OUT_UINT(hf_afs_fs_status_author); \
193                 OUT_UINT(hf_afs_fs_status_owner); \
194                 OUT_UINT(hf_afs_fs_status_calleraccess); \
195                 OUT_UINT(hf_afs_fs_status_anonymousaccess); \
196                 OUT_UINT(hf_afs_fs_status_mode); \
197                 OUT_UINT(hf_afs_fs_status_parentvnode); \
198                 OUT_UINT(hf_afs_fs_status_parentunique); \
199                 OUT_UINT(hf_afs_fs_status_segsize); \
200                 OUT_DATE(hf_afs_fs_status_clientmodtime); \
201                 OUT_DATE(hf_afs_fs_status_servermodtime); \
202                 OUT_UINT(hf_afs_fs_status_group); \
203                 OUT_UINT(hf_afs_fs_status_synccounter); \
204                 OUT_UINT(hf_afs_fs_status_dataversionhigh); \
205                 OUT_UINT(hf_afs_fs_status_spare2); \
206                 OUT_UINT(hf_afs_fs_status_spare3); \
207                 OUT_UINT(hf_afs_fs_status_spare4); \
208                 tree = save; \
209         }
210
211 /* Output a VolSync */
212 #define OUT_FS_AFSVolSync() \
213         {       proto_tree *save, *ti; \
214                 ti = proto_tree_add_text(tree, tvb, offset, 6*4, \
215                         "VolSync"); \
216                 save = tree; \
217                 tree = proto_item_add_subtree(ti, ett_afs_volsync); \
218                 OUT_DATE(hf_afs_fs_volsync_spare1); \
219                 OUT_UINT(hf_afs_fs_volsync_spare2); \
220                 OUT_UINT(hf_afs_fs_volsync_spare3); \
221                 OUT_UINT(hf_afs_fs_volsync_spare4); \
222                 OUT_UINT(hf_afs_fs_volsync_spare5); \
223                 OUT_UINT(hf_afs_fs_volsync_spare6); \
224                 tree = save; \
225         }
226
227 /* Output a AFSCBFids */
228 #define OUT_FS_AFSCBFids() \
229         { \
230                 guint32 j,i; \
231                 j = tvb_get_ntohl(tvb, offset); \
232                 offset += 4; \
233                 for (i=0; i<j; i++) { \
234                         OUT_FS_AFSFid("Target"); \
235                 } \
236         }       
237
238 /* Output a ViceIds */
239 #define OUT_FS_ViceIds() \
240         { \
241                 unsigned int j,i; \
242                 j = tvb_get_guint8(tvb,offset); \
243                 offset += 1; \
244                 for (i=0; i<j; i++) { \
245                         OUT_UINT(hf_afs_fs_viceid); \
246                 } \
247         }
248
249 /* Output a IPAddrs */
250 #define OUT_FS_IPAddrs() \
251         { \
252                 unsigned int j,i; \
253                 j = tvb_get_guint8(tvb, offset); \
254                 offset += 1; \
255                 for (i=0; i<j; i++) { \
256                         OUT_IP(hf_afs_fs_ipaddr); \
257                 } \
258         }
259
260 /* Output a AFSCBs */
261 #define OUT_FS_AFSCBs() \
262         { \
263                 guint32 j,i; \
264                 j = tvb_get_ntohl(tvb,offset); \
265                 offset += 4; \
266                 for (i=0; i<j; i++) { \
267                         OUT_FS_AFSCallBack(); \
268                 } \
269         }
270
271
272 /* Output a AFSBulkStats */
273 #define OUT_FS_AFSBulkStats() \
274         { \
275                 guint32 j,i; \
276                 j = tvb_get_ntohl(tvb,offset); \
277                 offset += 4; \
278                 for (i=0; i<j; i++) { \
279                         OUT_FS_AFSFetchStatus("Status"); \
280                 } \
281         }
282
283 /* Output a AFSFetchVolumeStatus */
284 #define OUT_FS_AFSFetchVolumeStatus()
285
286 /* Output a AFSStoreVolumeStatus */
287 #define OUT_FS_AFSStoreVolumeStatus()
288
289 /* Output a ViceStatistics structure */
290 #define OUT_FS_ViceStatistics()
291
292 /* Output a AFS_CollData structure */
293 #define OUT_FS_AFS_CollData()
294
295 /* Output a VolumeInfo structure */
296 #define OUT_FS_VolumeInfo()
297
298 /* Output an AFS Token - might just be bytes though */
299 #define OUT_FS_AFSTOKEN() VECOUT(hf_afs_fs_token, 1024)
300
301 /* Output a AFS acl */
302 #define ACLOUT(who, positive, acl, bytes) \
303         {       proto_tree *save, *ti; \
304                 int tmpoffset; \
305                 int acllen; \
306                 char tmp[10]; \
307                 tmp[0] = 0; \
308                 if ( acl & PRSFS_READ ) strcat(tmp, "r"); \
309                 if ( acl & PRSFS_LOOKUP ) strcat(tmp, "l"); \
310                 if ( acl & PRSFS_INSERT ) strcat(tmp, "i"); \
311                 if ( acl & PRSFS_DELETE ) strcat(tmp, "d"); \
312                 if ( acl & PRSFS_WRITE ) strcat(tmp, "w"); \
313                 if ( acl & PRSFS_LOCK ) strcat(tmp, "k"); \
314                 if ( acl & PRSFS_ADMINISTER ) strcat(tmp, "a"); \
315                 ti = proto_tree_add_text(tree, tvb, offset, bytes, \
316                         "ACL:  %s %s%s", \
317                         who, tmp, positive ? "" : " (negative)"); \
318                 save = tree; \
319                 tree = proto_item_add_subtree(ti, ett_afs_acl); \
320                 proto_tree_add_string(tree,hf_afs_fs_acl_entity, tvb,offset,strlen(who), who);\
321                 tmpoffset = offset + strlen(who) + 1; \
322                 acllen = bytes - strlen(who) - 1; \
323                 proto_tree_add_uint(tree,hf_afs_fs_acl_r, tvb,tmpoffset,acllen,acl);\
324                 proto_tree_add_uint(tree,hf_afs_fs_acl_l, tvb,tmpoffset,acllen,acl);\
325                 proto_tree_add_uint(tree,hf_afs_fs_acl_i, tvb,tmpoffset,acllen,acl);\
326                 proto_tree_add_uint(tree,hf_afs_fs_acl_d, tvb,tmpoffset,acllen,acl);\
327                 proto_tree_add_uint(tree,hf_afs_fs_acl_w, tvb,tmpoffset,acllen,acl);\
328                 proto_tree_add_uint(tree,hf_afs_fs_acl_k, tvb,tmpoffset,acllen,acl);\
329                 proto_tree_add_uint(tree,hf_afs_fs_acl_a, tvb,tmpoffset,acllen,acl);\
330                 tree = save; \
331         }
332
333 /* output a bozo_key */
334 #define OUT_BOS_KEY() \
335         OUT_BYTES(hf_afs_bos_key, 8);
336
337 /* output a bozo_key */
338 #define OUT_BOS_KEYINFO() \
339         OUT_TIMESTAMP(hf_afs_bos_keymodtime); \
340         OUT_UINT(hf_afs_bos_keychecksum); \
341         OUT_UINT(hf_afs_bos_keyspare2);
342
343 /* output a bozo_netKTime */
344 #define OUT_BOS_TIME() \
345         SKIP(4); SKIP(2); SKIP(2); SKIP(2); SKIP(2);
346
347 /* output a bozo_status */
348 #define OUT_BOS_STATUS() \
349         SKIP(10 * 4);
350
351 /* output a ubik interface addr array */
352 #define OUT_UBIK_InterfaceAddrs() \
353     { \
354         unsigned int i,j,seen_null=0; \
355         for (i=0; i<255; i++) { \
356                 j = tvb_get_ntohl(tvb, offset); \
357                 if ( j != 0 ) { \
358                         OUT_IP(hf_afs_ubik_interface); \
359                         seen_null = 0; \
360                 } else { \
361                         if ( ! seen_null ) { \
362                         proto_tree_add_text(tree, tvb, offset, \
363                                 tvb_length_remaining(tvb, offset), \
364                                 "Null Interface Addresses"); \
365                                 seen_null = 1; \
366                         } \
367                         offset += 4; \
368                 }\
369         } \
370     }
371
372 #define OUT_UBIK_DebugOld() \
373         { \
374                 OUT_DATE(hf_afs_ubik_now); \
375                 OUT_DATE(hf_afs_ubik_lastyestime); \
376                 OUT_IP(hf_afs_ubik_lastyeshost); \
377                 OUT_UINT(hf_afs_ubik_lastyesstate); \
378                 OUT_DATE(hf_afs_ubik_lastyesclaim); \
379                 OUT_IP(hf_afs_ubik_lowesthost); \
380                 OUT_DATE(hf_afs_ubik_lowesttime); \
381                 OUT_IP(hf_afs_ubik_synchost); \
382                 OUT_DATE(hf_afs_ubik_synctime); \
383                 OUT_UBIKVERSION("Sync Version"); \
384                 OUT_UBIKVERSION("Sync TID"); \
385                 OUT_UINT(hf_afs_ubik_amsyncsite); \
386                 OUT_DATE(hf_afs_ubik_syncsiteuntil); \
387                 OUT_UINT(hf_afs_ubik_nservers); \
388                 OUT_UINT(hf_afs_ubik_lockedpages); \
389                 OUT_UINT(hf_afs_ubik_writelockedpages); \
390                 OUT_UBIKVERSION("Local Version"); \
391                 OUT_UINT(hf_afs_ubik_activewrite); \
392                 OUT_UINT(hf_afs_ubik_tidcounter); \
393                 OUT_UINT(hf_afs_ubik_anyreadlocks); \
394                 OUT_UINT(hf_afs_ubik_anywritelocks); \
395                 OUT_UINT(hf_afs_ubik_recoverystate); \
396                 OUT_UINT(hf_afs_ubik_currenttrans); \
397                 OUT_UINT(hf_afs_ubik_writetrans); \
398                 OUT_DATE(hf_afs_ubik_epochtime); \
399         }
400
401 #define OUT_UBIK_SDebugOld() \
402         { \
403                 OUT_IP(hf_afs_ubik_addr); \
404                 OUT_DATE(hf_afs_ubik_lastvotetime); \
405                 OUT_DATE(hf_afs_ubik_lastbeaconsent); \
406                 OUT_UINT(hf_afs_ubik_lastvote); \
407                 OUT_UBIKVERSION("Remote Version"); \
408                 OUT_UINT(hf_afs_ubik_currentdb); \
409                 OUT_UINT(hf_afs_ubik_beaconsincedown); \
410                 OUT_UINT(hf_afs_ubik_up); \
411         }
412
413 /* Skip a certain number of bytes */
414 #define SKIP(bytes) \
415         offset += bytes;
416         
417 /* Raw data - to end of frame */
418 #define OUT_BYTES_ALL(field) OUT_BYTES(field, tvb_length_remaining(tvb,offset))
419
420 /* Raw data */
421 #define OUT_BYTES(field, bytes) \
422         proto_tree_add_item(tree, field, tvb, offset, bytes, FALSE);\
423         offset += bytes;
424
425 /* Output a rx style string, up to a maximum length first 
426    4 bytes - length, then char data */
427 #define OUT_STRING(field) \
428         {       int i; \
429                 i = tvb_get_ntohl(tvb, offset); \
430                 offset += 4; \
431                 if ( i > 0 ) { \
432                         char *tmp; \
433                         tmp = g_malloc(i+1); \
434                         memcpy(tmp, tvb_get_ptr(tvb,offset,i), i); \
435                         tmp[i] = '\0'; \
436                         proto_tree_add_string(tree, field, tvb, offset-4, i+4, \
437                         (void *)tmp); \
438                         g_free(tmp); \
439                 } else { \
440                         proto_tree_add_string(tree, field, tvb, offset-4, 4, \
441                         ""); \
442                 } \
443                 offset += i; \
444         }
445
446 /* Output a fixed length vectorized string (each char is a 32 bit int) */
447 #define VECOUT(field, length) \
448         {       char tmp[length+1]; \
449                 int i,soff; \
450                 soff = offset;\
451                 for (i=0; i<length; i++)\
452                 {\
453                         tmp[i] = (char) tvb_get_ntohl(tvb, offset);\
454                         offset += sizeof(guint32);\
455                 }\
456                 tmp[length] = '\0';\
457                 proto_tree_add_string(tree, field, tvb, soff, length, tmp);\
458         }
459
460 /* Skip the opcode */
461 #define SKIP_OPCODE() \
462         { \
463                 SKIP(sizeof(guint32)); \
464         }
465
466 /* Output a UBIK version code */
467 #define OUT_UBIKVERSION(label) \
468         {       proto_tree *save, *ti; \
469                 unsigned int epoch,counter; \
470                 nstime_t ts; \
471                 epoch = tvb_get_ntohl(tvb, offset); \
472                 offset += 4; \
473                 counter = tvb_get_ntohl(tvb, offset); \
474                 offset += 4; \
475                 ts.secs = epoch; \
476                 ts.nsecs = 0; \
477                 ti = proto_tree_add_text(tree, tvb, offset-8, 8, \
478                         "UBIK Version (%s): %u.%u", label, epoch, counter ); \
479                 save = tree; \
480                 tree = proto_item_add_subtree(ti, ett_afs_ubikver); \
481                 if ( epoch != 0 ) \
482                 proto_tree_add_time(tree,hf_afs_ubik_version_epoch, tvb,offset-8, \
483                         sizeof(guint32),&ts); \
484                 else \
485                         proto_tree_add_text(tree, tvb, offset-8, \
486                         sizeof(guint32),"Epoch: 0"); \
487                 proto_tree_add_uint(tree,hf_afs_ubik_version_counter, tvb,offset-4, \
488                         sizeof(guint32),counter); \
489                 tree = save; \
490         }