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.
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 #define OUT_UINT64(field) \
60 proto_tree_add_item(tree, field, tvb, offset, 8, FALSE); \
63 /* Output a unsigned integer, stored into field 'field'
64 Assumes it is in network byte order, converts to host before using */
65 #define OUT_INT64(field) \
66 proto_tree_add_item(tree, field, tvb, offset, 8, FALSE); \
69 /* Output a unsigned integer, stored into field 'field'
70 Assumes it is in network byte order, converts to host before using,
71 Note - does not increment offset, so can be used repeatedly for bitfields */
72 #define DISP_UINT(field) \
73 proto_tree_add_uint(tree,field,tvb,offset,sizeof(guint32),tvb_get_ntohl(tvb, offset));
75 /* Output an IPv4 address, stored into field 'field' */
76 #define OUT_IP(field) \
77 proto_tree_add_ipv4(tree,field,tvb,offset,sizeof(gint32),\
78 tvb_get_letohl(tvb, offset));\
81 /* Output a simple rx array */
82 #define OUT_RXArray8(func) \
85 j = tvb_get_guint8(tvb, offset); \
87 for (i=0; i<j; i++) { \
92 /* Output a simple rx array */
93 #define OUT_RXArray32(func) \
96 j = tvb_get_ntohl(tvb, offset); \
97 offset += sizeof(guint32); \
98 for (i=0; i<j; i++) { \
103 /* Output a UNIX seconds/microseconds timestamp, after converting to an
105 #define OUT_TIMESTAMP(field) \
107 ts.secs = tvb_get_ntohl(tvb, offset); \
108 ts.nsecs = tvb_get_ntohl(tvb, offset)*1000; \
109 proto_tree_add_time(tree,field, tvb,offset,2*sizeof(guint32),&ts); \
113 /* Output a seconds-only time value, after converting to an nstime_t;
114 this can be an absolute time as a UNIX time-since-epoch, or a
115 relative time in seconds */
116 #define OUT_TIMESECS(field) \
118 ts.secs = tvb_get_ntohl(tvb, offset); \
120 proto_tree_add_time(tree,field, tvb,offset,sizeof(guint32),&ts); \
124 /* Output a rx style string, up to a maximum length first
125 4 bytes - length, then char data */
126 #define OUT_RXString(field) \
130 i = tvb_get_ntohl(tvb, offset); \
132 p = tvb_get_ptr(tvb,offset,i); \
133 len = ((i+4-1)/4)*4; \
134 tmp = g_malloc(i+1); \
137 proto_tree_add_string(tree, field, tvb, offset-4, len+4, \
143 /* Output a fixed length vectorized string (each char is a 32 bit int) */
144 #define OUT_RXStringV(field, length) \
145 { char tmp[length+1]; \
148 for (i=0; i<length; i++)\
150 tmp[i] = (char) tvb_get_ntohl(tvb, offset);\
151 offset += sizeof(guint32);\
154 proto_tree_add_string(tree, field, tvb, soff, length*sizeof(guint32), tmp);\
158 /* Output a callback */
159 #define OUT_FS_AFSCallBack() \
160 { proto_tree *save, *ti; \
161 ti = proto_tree_add_text(tree, tvb, offset, 3*4, "Callback"); \
163 tree = proto_item_add_subtree(ti, ett_afs_callback); \
164 OUT_UINT(hf_afs_fs_callback_version); \
165 OUT_TIMESECS(hf_afs_fs_callback_expires); \
166 OUT_UINT(hf_afs_fs_callback_type); \
170 /* Output a callback */
171 #define OUT_CB_AFSCallBack() \
172 { proto_tree *save, *ti; \
173 ti = proto_tree_add_text(tree, tvb, offset, 3*4, "Callback"); \
175 tree = proto_item_add_subtree(ti, ett_afs_callback); \
176 OUT_UINT(hf_afs_cb_callback_version); \
177 OUT_TIMESECS(hf_afs_cb_callback_expires); \
178 OUT_UINT(hf_afs_cb_callback_type); \
182 /* Output a File ID */
183 #define OUT_FS_AFSFid(label) \
184 { proto_tree *save, *ti; \
185 ti = proto_tree_add_text(tree, tvb, offset, 3*4, \
186 "FileID (%s)", label); \
188 tree = proto_item_add_subtree(ti, ett_afs_fid); \
189 OUT_UINT(hf_afs_fs_fid_volume); \
190 OUT_UINT(hf_afs_fs_fid_vnode); \
191 OUT_UINT(hf_afs_fs_fid_uniqifier); \
195 /* Output a Status mask */
196 #define OUT_FS_STATUSMASK() \
197 { proto_tree *save, *ti; \
199 mask = tvb_get_ntohl(tvb, offset); \
200 ti = proto_tree_add_uint(tree, hf_afs_fs_status_mask, tvb, offset, \
201 sizeof(guint32), mask); \
203 tree = proto_item_add_subtree(ti, ett_afs_status_mask); \
204 proto_tree_add_boolean(tree, hf_afs_fs_status_mask_setmodtime, \
205 tvb,offset,sizeof(guint32), mask); \
206 proto_tree_add_boolean(tree, hf_afs_fs_status_mask_setowner, \
207 tvb,offset,sizeof(guint32), mask); \
208 proto_tree_add_boolean(tree, hf_afs_fs_status_mask_setgroup, \
209 tvb,offset,sizeof(guint32), mask); \
210 proto_tree_add_boolean(tree, hf_afs_fs_status_mask_setmode, \
211 tvb,offset,sizeof(guint32), mask); \
212 proto_tree_add_boolean(tree, hf_afs_fs_status_mask_setsegsize, \
213 tvb,offset,sizeof(guint32), mask); \
214 proto_tree_add_boolean(tree, hf_afs_fs_status_mask_fsync, \
215 tvb,offset,sizeof(guint32), mask); \
220 /* Output vldb flags */
221 #define OUT_VLDB_Flags() \
222 { proto_tree *save, *ti; \
224 flags = tvb_get_ntohl(tvb, offset); \
225 ti = proto_tree_add_uint(tree, hf_afs_vldb_flags, tvb, offset, \
226 sizeof(guint32), flags); \
228 tree = proto_item_add_subtree(ti, ett_afs_vldb_flags); \
229 proto_tree_add_boolean(tree, hf_afs_vldb_flags_rwexists, \
230 tvb,offset,sizeof(guint32), flags); \
231 proto_tree_add_boolean(tree, hf_afs_vldb_flags_roexists, \
232 tvb,offset,sizeof(guint32), flags); \
233 proto_tree_add_boolean(tree, hf_afs_vldb_flags_bkexists, \
234 tvb,offset,sizeof(guint32), flags); \
235 proto_tree_add_boolean(tree, hf_afs_vldb_flags_dfsfileset, \
236 tvb,offset,sizeof(guint32), flags); \
243 /* Output a File ID */
244 #define OUT_CB_AFSFid(label) \
245 { proto_tree *save, *ti; \
246 ti = proto_tree_add_text(tree, tvb, offset, 3*4, \
247 "FileID (%s)", label); \
249 tree = proto_item_add_subtree(ti, ett_afs_fid); \
250 OUT_UINT(hf_afs_cb_fid_volume); \
251 OUT_UINT(hf_afs_cb_fid_vnode); \
252 OUT_UINT(hf_afs_cb_fid_uniqifier); \
256 /* Output a StoreStatus */
257 #define OUT_FS_AFSStoreStatus(label) \
258 { proto_tree *save, *ti; \
259 ti = proto_tree_add_text(tree, tvb, offset, 6*4, \
262 tree = proto_item_add_subtree(ti, ett_afs_status); \
263 OUT_FS_STATUSMASK(); \
264 OUT_TIMESECS(hf_afs_fs_status_clientmodtime); \
265 OUT_UINT(hf_afs_fs_status_owner); \
266 OUT_UINT(hf_afs_fs_status_group); \
267 OUT_UINT(hf_afs_fs_status_mode); \
268 OUT_UINT(hf_afs_fs_status_segsize); \
272 /* Output a FetchStatus */
273 #define OUT_FS_AFSFetchStatus(label) \
274 { proto_tree *save, *ti; \
275 ti = proto_tree_add_text(tree, tvb, offset, 21*4, \
278 tree = proto_item_add_subtree(ti, ett_afs_status); \
279 OUT_UINT(hf_afs_fs_status_interfaceversion); \
280 OUT_UINT(hf_afs_fs_status_filetype); \
281 OUT_UINT(hf_afs_fs_status_linkcount); \
282 OUT_UINT(hf_afs_fs_status_length); \
283 OUT_UINT(hf_afs_fs_status_dataversion); \
284 OUT_UINT(hf_afs_fs_status_author); \
285 OUT_UINT(hf_afs_fs_status_owner); \
286 OUT_UINT(hf_afs_fs_status_calleraccess); \
287 OUT_UINT(hf_afs_fs_status_anonymousaccess); \
288 OUT_UINT(hf_afs_fs_status_mode); \
289 OUT_UINT(hf_afs_fs_status_parentvnode); \
290 OUT_UINT(hf_afs_fs_status_parentunique); \
291 OUT_UINT(hf_afs_fs_status_segsize); \
292 OUT_TIMESECS(hf_afs_fs_status_clientmodtime); \
293 OUT_TIMESECS(hf_afs_fs_status_servermodtime); \
294 OUT_UINT(hf_afs_fs_status_group); \
295 OUT_UINT(hf_afs_fs_status_synccounter); \
296 OUT_UINT(hf_afs_fs_status_dataversionhigh); \
297 OUT_UINT(hf_afs_fs_status_spare2); \
298 OUT_UINT(hf_afs_fs_status_spare3); \
299 OUT_UINT(hf_afs_fs_status_spare4); \
303 /* Output a VolSync */
304 #define OUT_FS_AFSVolSync() \
305 { proto_tree *save, *ti; \
306 ti = proto_tree_add_text(tree, tvb, offset, 6*4, \
309 tree = proto_item_add_subtree(ti, ett_afs_volsync); \
310 OUT_TIMESECS(hf_afs_fs_volsync_spare1); \
311 OUT_UINT(hf_afs_fs_volsync_spare2); \
312 OUT_UINT(hf_afs_fs_volsync_spare3); \
313 OUT_UINT(hf_afs_fs_volsync_spare4); \
314 OUT_UINT(hf_afs_fs_volsync_spare5); \
315 OUT_UINT(hf_afs_fs_volsync_spare6); \
319 /* Output a AFSCBFids */
320 #define OUT_FS_AFSCBFids() \
321 OUT_RXArray32(OUT_FS_AFSFid("Target"));
323 /* Output a ViceIds */
324 #define OUT_FS_ViceIds() \
325 OUT_RXArray8(OUT_UINT(hf_afs_fs_viceid));
327 /* Output a IPAddrs */
328 #define OUT_FS_IPAddrs() \
329 OUT_RXArray8(OUT_IP(hf_afs_fs_ipaddr));
331 /* Output a AFSCBs */
332 #define OUT_FS_AFSCBs() \
333 OUT_RXArray32(OUT_FS_AFSCallBack());
335 /* Output a AFSBulkStats */
336 #define OUT_FS_AFSBulkStats() \
337 OUT_RXArray32(OUT_FS_AFSFetchStatus("Status"));
339 /* Output a AFSFetchVolumeStatus */
340 #define OUT_FS_AFSFetchVolumeStatus()
342 /* Output a AFSStoreVolumeStatus */
343 #define OUT_FS_AFSStoreVolumeStatus()
345 /* Output a ViceStatistics structure */
346 #define OUT_FS_ViceStatistics()
348 /* Output a AFS_CollData structure */
349 #define OUT_FS_AFS_CollData()
351 /* Output a VolumeInfo structure */
352 #define OUT_FS_VolumeInfo()
354 /* Output an AFS Token - might just be bytes though */
355 #define OUT_FS_AFSTOKEN() OUT_RXStringV(hf_afs_fs_token, 1024)
357 /* Output a AFS acl */
358 #define ACLOUT(who, positive, acl, bytes) \
359 { proto_tree *save, *ti; \
364 if ( acl & PRSFS_READ ) strcat(tmp, "r"); \
365 if ( acl & PRSFS_LOOKUP ) strcat(tmp, "l"); \
366 if ( acl & PRSFS_INSERT ) strcat(tmp, "i"); \
367 if ( acl & PRSFS_DELETE ) strcat(tmp, "d"); \
368 if ( acl & PRSFS_WRITE ) strcat(tmp, "w"); \
369 if ( acl & PRSFS_LOCK ) strcat(tmp, "k"); \
370 if ( acl & PRSFS_ADMINISTER ) strcat(tmp, "a"); \
371 ti = proto_tree_add_text(tree, tvb, offset, bytes, \
373 who, tmp, positive ? "" : " (negative)"); \
375 tree = proto_item_add_subtree(ti, ett_afs_acl); \
376 proto_tree_add_string(tree,hf_afs_fs_acl_entity, tvb,offset,strlen(who), who);\
377 tmpoffset = offset + strlen(who) + 1; \
378 acllen = bytes - strlen(who) - 1; \
379 proto_tree_add_boolean(tree,hf_afs_fs_acl_r, tvb,tmpoffset,acllen,acl);\
380 proto_tree_add_boolean(tree,hf_afs_fs_acl_l, tvb,tmpoffset,acllen,acl);\
381 proto_tree_add_boolean(tree,hf_afs_fs_acl_i, tvb,tmpoffset,acllen,acl);\
382 proto_tree_add_boolean(tree,hf_afs_fs_acl_d, tvb,tmpoffset,acllen,acl);\
383 proto_tree_add_boolean(tree,hf_afs_fs_acl_w, tvb,tmpoffset,acllen,acl);\
384 proto_tree_add_boolean(tree,hf_afs_fs_acl_k, tvb,tmpoffset,acllen,acl);\
385 proto_tree_add_boolean(tree,hf_afs_fs_acl_a, tvb,tmpoffset,acllen,acl);\
390 #define OUT_UUID(x) \
391 OUT_BYTES(x, 11*sizeof(guint32));
392 #define SKIP_UUID() \
393 SKIP(11*sizeof(guint32));
396 /* Output a bulkaddr */
397 #define OUT_VLDB_BulkAddr() \
398 OUT_RXArray32(OUT_IP(hf_afs_vldb_serverip));
400 /* output a bozo_key */
401 #define OUT_BOS_KEY() \
402 OUT_BYTES(hf_afs_bos_key, 8);
404 /* output a bozo_key */
405 #define OUT_BOS_KEYINFO() \
406 OUT_TIMESTAMP(hf_afs_bos_keymodtime); \
407 OUT_UINT(hf_afs_bos_keychecksum); \
408 OUT_UINT(hf_afs_bos_keyspare2);
410 /* output a bozo_netKTime */
411 #define OUT_BOS_TIME() \
412 SKIP(4); SKIP(2); SKIP(2); SKIP(2); SKIP(2);
414 /* output a bozo_status */
415 #define OUT_BOS_STATUS() \
418 /* output a ubik interface addr array */
419 #define OUT_UBIK_InterfaceAddrs() \
421 unsigned int i,j,seen_null=0; \
422 for (i=0; i<255; i++) { \
423 j = tvb_get_ntohl(tvb, offset); \
425 OUT_IP(hf_afs_ubik_interface); \
428 if ( ! seen_null ) { \
429 proto_tree_add_text(tree, tvb, offset, \
430 tvb_length_remaining(tvb, offset), \
431 "Null Interface Addresses"); \
439 #define OUT_UBIK_DebugOld() \
441 OUT_TIMESECS(hf_afs_ubik_now); \
442 OUT_TIMESECS(hf_afs_ubik_lastyestime); \
443 OUT_IP(hf_afs_ubik_lastyeshost); \
444 OUT_UINT(hf_afs_ubik_lastyesstate); \
445 OUT_TIMESECS(hf_afs_ubik_lastyesclaim); \
446 OUT_IP(hf_afs_ubik_lowesthost); \
447 OUT_TIMESECS(hf_afs_ubik_lowesttime); \
448 OUT_IP(hf_afs_ubik_synchost); \
449 OUT_TIMESECS(hf_afs_ubik_synctime); \
450 OUT_UBIKVERSION("Sync Version"); \
451 OUT_UBIKVERSION("Sync TID"); \
452 OUT_UINT(hf_afs_ubik_amsyncsite); \
453 OUT_TIMESECS(hf_afs_ubik_syncsiteuntil); \
454 OUT_UINT(hf_afs_ubik_nservers); \
455 OUT_UINT(hf_afs_ubik_lockedpages); \
456 OUT_UINT(hf_afs_ubik_writelockedpages); \
457 OUT_UBIKVERSION("Local Version"); \
458 OUT_UINT(hf_afs_ubik_activewrite); \
459 OUT_UINT(hf_afs_ubik_tidcounter); \
460 OUT_UINT(hf_afs_ubik_anyreadlocks); \
461 OUT_UINT(hf_afs_ubik_anywritelocks); \
462 OUT_UINT(hf_afs_ubik_recoverystate); \
463 OUT_UINT(hf_afs_ubik_currenttrans); \
464 OUT_UINT(hf_afs_ubik_writetrans); \
465 OUT_TIMESECS(hf_afs_ubik_epochtime); \
468 #define OUT_UBIK_SDebugOld() \
470 OUT_IP(hf_afs_ubik_addr); \
471 OUT_TIMESECS(hf_afs_ubik_lastvotetime); \
472 OUT_TIMESECS(hf_afs_ubik_lastbeaconsent); \
473 OUT_UINT(hf_afs_ubik_lastvote); \
474 OUT_UBIKVERSION("Remote Version"); \
475 OUT_UINT(hf_afs_ubik_currentdb); \
476 OUT_UINT(hf_afs_ubik_beaconsincedown); \
477 OUT_UINT(hf_afs_ubik_up); \
480 /* Skip a certain number of bytes */
481 #define SKIP(bytes) \
484 /* Raw data - to end of frame */
485 #define OUT_BYTES_ALL(field) OUT_BYTES(field, tvb_length_remaining(tvb,offset))
488 #define OUT_BYTES(field, bytes) \
489 proto_tree_add_item(tree, field, tvb, offset, bytes, FALSE);\
494 /* Skip the opcode */
495 #define SKIP_OPCODE() \
497 SKIP(sizeof(guint32)); \
500 /* Output a UBIK version code */
501 #define OUT_UBIKVERSION(label) \
502 { proto_tree *save, *ti; \
503 unsigned int epoch,counter; \
505 epoch = tvb_get_ntohl(tvb, offset); \
507 counter = tvb_get_ntohl(tvb, offset); \
511 ti = proto_tree_add_text(tree, tvb, offset-8, 8, \
512 "UBIK Version (%s): %u.%u", label, epoch, counter ); \
514 tree = proto_item_add_subtree(ti, ett_afs_ubikver); \
516 proto_tree_add_time(tree,hf_afs_ubik_version_epoch, tvb,offset-8, \
517 sizeof(guint32),&ts); \
519 proto_tree_add_text(tree, tvb, offset-8, \
520 sizeof(guint32),"Epoch: 0"); \
521 proto_tree_add_uint(tree,hf_afs_ubik_version_counter, tvb,offset-4, \
522 sizeof(guint32),counter); \
526 /* Output a kauth getticket request */
527 #define OUT_KAUTH_GetTicket() \
530 OUT_UINT(hf_afs_kauth_kvno); \
531 OUT_RXString(hf_afs_kauth_domain); \
532 len = tvb_get_ntohl(tvb, offset); \
534 OUT_BYTES(hf_afs_kauth_data, len); \
535 OUT_RXString(hf_afs_kauth_princ); \
536 OUT_RXString(hf_afs_kauth_realm); \