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.
11 * $Id: packet-afs-macros.h,v 1.13 2002/01/18 21:30:05 nneul Exp $
13 * Ethereal - Network traffic analyzer
14 * By Gerald Combs <gerald@ethereal.com>
15 * Copyright 1998 Gerald Combs
17 * Copied from packet-tftp.c
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.
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.
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.
37 * Macros for helper dissection routines
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.
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)); \
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)); \
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));
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));\
69 /* Output a UNIX seconds/microseconds timestamp, after converting to an
71 #define OUT_TIMESTAMP(field) \
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); \
79 /* Output a UNIX seconds-only timestamp, after converting to an nstime_t */
80 #define OUT_DATE(field) \
82 ts.secs = tvb_get_ntohl(tvb, offset); \
84 proto_tree_add_time(tree,field, tvb,offset,sizeof(guint32),&ts); \
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"); \
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); \
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"); \
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); \
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); \
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); \
126 /* Output a Status mask */
127 #define OUT_FS_STATUSMASK() \
128 { proto_tree *save, *ti; \
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); \
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); \
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); \
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); \
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, \
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); \
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, \
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); \
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, \
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); \
227 /* Output a AFSCBFids */
228 #define OUT_FS_AFSCBFids() \
231 j = tvb_get_ntohl(tvb, offset); \
233 for (i=0; i<j; i++) { \
234 OUT_FS_AFSFid("Target"); \
238 /* Output a ViceIds */
239 #define OUT_FS_ViceIds() \
242 j = tvb_get_guint8(tvb,offset); \
244 for (i=0; i<j; i++) { \
245 OUT_UINT(hf_afs_fs_viceid); \
249 /* Output a IPAddrs */
250 #define OUT_FS_IPAddrs() \
253 j = tvb_get_guint8(tvb, offset); \
255 for (i=0; i<j; i++) { \
256 OUT_IP(hf_afs_fs_ipaddr); \
260 /* Output a AFSCBs */
261 #define OUT_FS_AFSCBs() \
264 j = tvb_get_ntohl(tvb,offset); \
266 for (i=0; i<j; i++) { \
267 OUT_FS_AFSCallBack(); \
272 /* Output a AFSBulkStats */
273 #define OUT_FS_AFSBulkStats() \
276 j = tvb_get_ntohl(tvb,offset); \
278 for (i=0; i<j; i++) { \
279 OUT_FS_AFSFetchStatus("Status"); \
283 /* Output a AFSFetchVolumeStatus */
284 #define OUT_FS_AFSFetchVolumeStatus()
286 /* Output a AFSStoreVolumeStatus */
287 #define OUT_FS_AFSStoreVolumeStatus()
289 /* Output a ViceStatistics structure */
290 #define OUT_FS_ViceStatistics()
292 /* Output a AFS_CollData structure */
293 #define OUT_FS_AFS_CollData()
295 /* Output a VolumeInfo structure */
296 #define OUT_FS_VolumeInfo()
298 /* Output an AFS Token - might just be bytes though */
299 #define OUT_FS_AFSTOKEN() VECOUT(hf_afs_fs_token, 1024)
301 /* Output a AFS acl */
302 #define ACLOUT(who, positive, acl, bytes) \
303 { proto_tree *save, *ti; \
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, \
317 who, tmp, positive ? "" : " (negative)"); \
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);\
333 /* output a bozo_key */
334 #define OUT_BOS_KEY() \
335 OUT_BYTES(hf_afs_bos_key, 8);
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);
343 /* output a bozo_netKTime */
344 #define OUT_BOS_TIME() \
345 SKIP(4); SKIP(2); SKIP(2); SKIP(2); SKIP(2);
347 /* output a bozo_status */
348 #define OUT_BOS_STATUS() \
351 /* output a ubik interface addr array */
352 #define OUT_UBIK_InterfaceAddrs() \
354 unsigned int i,j,seen_null=0; \
355 for (i=0; i<255; i++) { \
356 j = tvb_get_ntohl(tvb, offset); \
358 OUT_IP(hf_afs_ubik_interface); \
361 if ( ! seen_null ) { \
362 proto_tree_add_text(tree, tvb, offset, \
363 tvb_length_remaining(tvb, offset), \
364 "Null Interface Addresses"); \
372 #define OUT_UBIK_DebugOld() \
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); \
401 #define OUT_UBIK_SDebugOld() \
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); \
413 /* Skip a certain number of bytes */
414 #define SKIP(bytes) \
417 /* Raw data - to end of frame */
418 #define OUT_BYTES_ALL(field) OUT_BYTES(field, tvb_length_remaining(tvb,offset))
421 #define OUT_BYTES(field, bytes) \
422 proto_tree_add_item(tree, field, tvb, offset, bytes, FALSE);\
425 /* Output a rx style string, up to a maximum length first
426 4 bytes - length, then char data */
427 #define OUT_STRING(field) \
429 i = tvb_get_ntohl(tvb, offset); \
433 tmp = g_malloc(i+1); \
434 memcpy(tmp, tvb_get_ptr(tvb,offset,i), i); \
436 proto_tree_add_string(tree, field, tvb, offset-4, i+4, \
440 proto_tree_add_string(tree, field, tvb, offset-4, 4, \
446 /* Output a fixed length vectorized string (each char is a 32 bit int) */
447 #define VECOUT(field, length) \
448 { char tmp[length+1]; \
451 for (i=0; i<length; i++)\
453 tmp[i] = (char) tvb_get_ntohl(tvb, offset);\
454 offset += sizeof(guint32);\
457 proto_tree_add_string(tree, field, tvb, soff, length, tmp);\
460 /* Skip the opcode */
461 #define SKIP_OPCODE() \
463 SKIP(sizeof(guint32)); \
466 /* Output a UBIK version code */
467 #define OUT_UBIKVERSION(label) \
468 { proto_tree *save, *ti; \
469 unsigned int epoch,counter; \
471 epoch = tvb_get_ntohl(tvb, offset); \
473 counter = tvb_get_ntohl(tvb, offset); \
477 ti = proto_tree_add_text(tree, tvb, offset-8, 8, \
478 "UBIK Version (%s): %u.%u", label, epoch, counter ); \
480 tree = proto_item_add_subtree(ti, ett_afs_ubikver); \
482 proto_tree_add_time(tree,hf_afs_ubik_version_epoch, tvb,offset-8, \
483 sizeof(guint32),&ts); \
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); \