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.5 2000/11/03 22:38:07 nneul Exp $
13 * Ethereal - Network traffic analyzer
14 * By Gerald Combs <gerald@zing.org>
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 'curoffset', and that the offset
41 * should be incremented after performing the macro's operation.
44 /* Get the next available integer, be sure and call TRUNC beforehand */
45 #define GETINT() (pntohl(&pd[curoffset]))
47 /* Check if enough bytes are present, if not, return to caller
48 after adding a 'Truncated' message to tree */
49 #define TRUNC(bytes) \
50 if(!BYTES_ARE_IN_FRAME(curoffset,(bytes))) \
52 proto_tree_add_text(tree, NullTVB,curoffset, \
53 END_OF_FRAME,"Truncated"); \
54 /* not sure why, but this didn't work */ \
55 /* if (check_col(fd, COL_INFO)) */ \
56 /* col_append_fstr(fd, COL_INFO, " (TRUNCATED)"); */ \
60 /* Output a unsigned integer, stored into field 'field'
61 Assumes it is in network byte order, converts to host before using */
62 #define OUT_UINT(field) \
63 TRUNC(sizeof(guint32)) \
64 proto_tree_add_uint(tree,field, NullTVB,curoffset,sizeof(guint32), GETINT()); \
67 /* Output a unsigned integer, stored into field 'field'
68 Assumes it is in network byte order, converts to host before using */
69 #define OUT_INT(field) \
70 TRUNC(sizeof(guint32)) \
71 proto_tree_add_int(tree,field, NullTVB,curoffset,sizeof(gint32), GETINT()); \
74 /* Output a unsigned integer, stored into field 'field'
75 Assumes it is in network byte order, converts to host before using,
76 Note - does not increment offset, so can be used repeatedly for bitfields */
77 #define DISP_UINT(field) \
78 TRUNC(sizeof(guint32)) \
79 proto_tree_add_uint(tree,field, NullTVB,curoffset,sizeof(guint32), GETINT());
81 /* Output an IPv4 address, stored into field 'field' */
82 #define OUT_IP(field) \
83 TRUNC(sizeof(gint32)) \
84 proto_tree_add_ipv4(tree,field, NullTVB,curoffset,sizeof(gint32),\
85 *((int*)&pd[curoffset]));\
88 /* Output a UNIX seconds/microseconds timestamp, after converting to a timeval */
89 #define OUT_TIMESTAMP(field) \
90 { struct timeval tv; \
91 TRUNC(2*sizeof(guint32)); \
92 tv.tv_sec = GETINT(); \
93 tv.tv_usec = GETINT(); \
94 proto_tree_add_time(tree,field, NullTVB,curoffset,2*sizeof(guint32),&tv); \
98 /* Output a UNIX seconds-only timestamp, after converting to a timeval */
99 #define OUT_DATE(field) \
100 { struct timeval tv; \
101 TRUNC(sizeof(guint32)); \
102 tv.tv_sec = GETINT(); \
104 proto_tree_add_time(tree,field, NullTVB,curoffset,sizeof(guint32),&tv); \
108 /* Output a callback */
109 #define OUT_FS_AFSCallBack() \
110 { proto_tree *save, *ti; \
111 ti = proto_tree_add_text(tree, NullTVB, curoffset, 3*4, "Callback"); \
113 tree = proto_item_add_subtree(ti, ett_afs_callback); \
114 TRUNC(3*sizeof(guint32)); \
115 OUT_UINT(hf_afs_fs_callback_version); \
116 OUT_DATE(hf_afs_fs_callback_expires); \
117 OUT_UINT(hf_afs_fs_callback_type); \
121 /* Output a callback */
122 #define OUT_CB_AFSCallBack() \
123 { proto_tree *save, *ti; \
124 ti = proto_tree_add_text(tree, NullTVB, curoffset, 3*4, "Callback"); \
126 tree = proto_item_add_subtree(ti, ett_afs_callback); \
127 TRUNC(3*sizeof(guint32)); \
128 OUT_UINT(hf_afs_cb_callback_version); \
129 OUT_DATE(hf_afs_cb_callback_expires); \
130 OUT_UINT(hf_afs_cb_callback_type); \
135 /* Output a File ID */
136 #define OUT_FS_AFSFid(label) \
137 { proto_tree *save, *ti; \
138 ti = proto_tree_add_text(tree, NullTVB, curoffset, 3*4, \
139 "FileID (%s)", label); \
141 tree = proto_item_add_subtree(ti, ett_afs_fid); \
142 OUT_UINT(hf_afs_fs_fid_volume); \
143 OUT_UINT(hf_afs_fs_fid_vnode); \
144 OUT_UINT(hf_afs_fs_fid_uniqifier); \
148 /* Output a Status mask */
149 #define OUT_FS_STATUSMASK() \
150 { proto_tree *save, *ti; \
152 TRUNC(sizeof(guint32)); \
154 ti = proto_tree_add_uint(tree, hf_afs_fs_status_mask, NullTVB, curoffset, \
155 sizeof(guint32), mask); \
157 tree = proto_item_add_subtree(ti, ett_afs_status_mask); \
158 proto_tree_add_uint(tree, hf_afs_fs_status_mask_setmodtime, \
159 NullTVB,curoffset,sizeof(guint32), mask); \
160 proto_tree_add_uint(tree, hf_afs_fs_status_mask_setowner, \
161 NullTVB,curoffset,sizeof(guint32), mask); \
162 proto_tree_add_uint(tree, hf_afs_fs_status_mask_setgroup, \
163 NullTVB,curoffset,sizeof(guint32), mask); \
164 proto_tree_add_uint(tree, hf_afs_fs_status_mask_setmode, \
165 NullTVB,curoffset,sizeof(guint32), mask); \
166 proto_tree_add_uint(tree, hf_afs_fs_status_mask_setsegsize, \
167 NullTVB,curoffset,sizeof(guint32), mask); \
168 proto_tree_add_uint(tree, hf_afs_fs_status_mask_fsync, \
169 NullTVB,curoffset,sizeof(guint32), mask); \
174 /* Output a File ID */
175 #define OUT_CB_AFSFid(label) \
176 { proto_tree *save, *ti; \
177 ti = proto_tree_add_text(tree, NullTVB, curoffset, 3*4, \
178 "FileID (%s)", label); \
180 tree = proto_item_add_subtree(ti, ett_afs_fid); \
181 OUT_UINT(hf_afs_cb_fid_volume); \
182 OUT_UINT(hf_afs_cb_fid_vnode); \
183 OUT_UINT(hf_afs_cb_fid_uniqifier); \
187 /* Output a StoreStatus */
188 #define OUT_FS_AFSStoreStatus(label) \
189 { proto_tree *save, *ti; \
190 ti = proto_tree_add_text(tree, NullTVB, curoffset, 6*4, \
193 tree = proto_item_add_subtree(ti, ett_afs_status); \
194 OUT_FS_STATUSMASK(); \
195 OUT_DATE(hf_afs_fs_status_clientmodtime); \
196 OUT_UINT(hf_afs_fs_status_owner); \
197 OUT_UINT(hf_afs_fs_status_group); \
198 OUT_UINT(hf_afs_fs_status_mode); \
199 OUT_UINT(hf_afs_fs_status_segsize); \
203 /* Output a FetchStatus */
204 #define OUT_FS_AFSFetchStatus(label) \
205 { proto_tree *save, *ti; \
206 ti = proto_tree_add_text(tree, NullTVB, curoffset, 21*4, \
209 tree = proto_item_add_subtree(ti, ett_afs_status); \
210 OUT_UINT(hf_afs_fs_status_interfaceversion); \
211 OUT_UINT(hf_afs_fs_status_filetype); \
212 OUT_UINT(hf_afs_fs_status_linkcount); \
213 OUT_UINT(hf_afs_fs_status_length); \
214 OUT_UINT(hf_afs_fs_status_dataversion); \
215 OUT_UINT(hf_afs_fs_status_author); \
216 OUT_UINT(hf_afs_fs_status_owner); \
217 OUT_UINT(hf_afs_fs_status_calleraccess); \
218 OUT_UINT(hf_afs_fs_status_anonymousaccess); \
219 OUT_UINT(hf_afs_fs_status_mode); \
220 OUT_UINT(hf_afs_fs_status_parentvnode); \
221 OUT_UINT(hf_afs_fs_status_parentunique); \
222 OUT_UINT(hf_afs_fs_status_segsize); \
223 OUT_DATE(hf_afs_fs_status_clientmodtime); \
224 OUT_DATE(hf_afs_fs_status_servermodtime); \
225 OUT_UINT(hf_afs_fs_status_group); \
226 OUT_UINT(hf_afs_fs_status_synccounter); \
227 OUT_UINT(hf_afs_fs_status_dataversionhigh); \
228 OUT_UINT(hf_afs_fs_status_spare2); \
229 OUT_UINT(hf_afs_fs_status_spare3); \
230 OUT_UINT(hf_afs_fs_status_spare4); \
234 /* Output a VolSync */
235 #define OUT_FS_AFSVolSync() \
236 { proto_tree *save, *ti; \
237 ti = proto_tree_add_text(tree, NullTVB, curoffset, 6*4, \
240 tree = proto_item_add_subtree(ti, ett_afs_volsync); \
241 OUT_UINT(hf_afs_fs_volsync_spare1); \
242 OUT_UINT(hf_afs_fs_volsync_spare2); \
243 OUT_UINT(hf_afs_fs_volsync_spare3); \
244 OUT_UINT(hf_afs_fs_volsync_spare4); \
245 OUT_UINT(hf_afs_fs_volsync_spare5); \
246 OUT_UINT(hf_afs_fs_volsync_spare6); \
250 /* Output a AFSCBFids */
251 #define OUT_FS_AFSCBFids() \
255 j = pntohl(&pd[curoffset]); \
257 for (i=0; i<j; i++) { \
258 OUT_FS_AFSFid("Target"); \
262 /* Output a ViceIds */
263 #define OUT_FS_ViceIds() \
267 j = pntohl(&pd[curoffset]); \
269 for (i=0; i<j; i++) { \
270 OUT_UINT(hf_afs_fs_viceid); \
274 /* Output a IPAddrs */
275 #define OUT_FS_IPAddrs() \
279 j = pntohl(&pd[curoffset]); \
281 for (i=0; i<j; i++) { \
282 OUT_IP(hf_afs_fs_ipaddr); \
286 /* Output a AFSCBs */
287 #define OUT_FS_AFSCBs() \
291 j = pntohl(&pd[curoffset]); \
293 for (i=0; i<j; i++) { \
294 OUT_FS_AFSCallBack(); \
299 /* Output a AFSBulkStats */
300 #define OUT_FS_AFSBulkStats() \
304 j = pntohl(&pd[curoffset]); \
306 for (i=0; i<j; i++) { \
307 OUT_FS_AFSFetchStatus("Status"); \
311 /* Output a AFSFetchVolumeStatus */
312 #define OUT_FS_AFSFetchVolumeStatus()
314 /* Output a AFSStoreVolumeStatus */
315 #define OUT_FS_AFSStoreVolumeStatus()
317 /* Output a ViceStatistics structure */
318 #define OUT_FS_ViceStatistics()
320 /* Output a AFS_CollData structure */
321 #define OUT_FS_AFS_CollData()
323 /* Output a VolumeInfo structure */
324 #define OUT_FS_VolumeInfo()
326 /* Output an AFS Token - might just be bytes though */
327 #define OUT_FS_AFSTOKEN() VECOUT(hf_afs_fs_token, 1024)
329 /* Output a AFS acl */
330 #define ACLOUT(who, positive, acl, bytes) \
331 { proto_tree *save, *ti; \
336 if ( acl & PRSFS_READ ) strcat(tmp, "r"); \
337 if ( acl & PRSFS_LOOKUP ) strcat(tmp, "l"); \
338 if ( acl & PRSFS_INSERT ) strcat(tmp, "i"); \
339 if ( acl & PRSFS_DELETE ) strcat(tmp, "d"); \
340 if ( acl & PRSFS_WRITE ) strcat(tmp, "w"); \
341 if ( acl & PRSFS_LOCK ) strcat(tmp, "k"); \
342 if ( acl & PRSFS_ADMINISTER ) strcat(tmp, "a"); \
343 ti = proto_tree_add_text(tree, NullTVB, curoffset, bytes, \
345 who, tmp, positive ? "" : " (negative)"); \
347 tree = proto_item_add_subtree(ti, ett_afs_acl); \
348 proto_tree_add_string(tree,hf_afs_fs_acl_entity, NullTVB,curoffset,strlen(who), who);\
349 tmpoffset = curoffset + strlen(who) + 1; \
350 acllen = bytes - strlen(who) - 1; \
351 proto_tree_add_uint(tree,hf_afs_fs_acl_r, NullTVB,tmpoffset,acllen,acl);\
352 proto_tree_add_uint(tree,hf_afs_fs_acl_l, NullTVB,tmpoffset,acllen,acl);\
353 proto_tree_add_uint(tree,hf_afs_fs_acl_i, NullTVB,tmpoffset,acllen,acl);\
354 proto_tree_add_uint(tree,hf_afs_fs_acl_d, NullTVB,tmpoffset,acllen,acl);\
355 proto_tree_add_uint(tree,hf_afs_fs_acl_w, NullTVB,tmpoffset,acllen,acl);\
356 proto_tree_add_uint(tree,hf_afs_fs_acl_k, NullTVB,tmpoffset,acllen,acl);\
357 proto_tree_add_uint(tree,hf_afs_fs_acl_a, NullTVB,tmpoffset,acllen,acl);\
361 /* output a bozo_key */
362 #define OUT_BOS_KEY() \
363 OUT_BYTES(hf_afs_bos_key, 8);
365 /* output a bozo_key */
366 #define OUT_BOS_KEYINFO() \
367 OUT_TIMESTAMP(hf_afs_bos_keymodtime); \
368 OUT_UINT(hf_afs_bos_keychecksum); \
369 OUT_UINT(hf_afs_bos_keyspare2);
371 /* output a bozo_netKTime */
372 #define OUT_BOS_TIME() \
373 SKIP(4); SKIP(2); SKIP(2); SKIP(2); SKIP(2);
375 /* output a bozo_status */
376 #define OUT_BOS_STATUS() \
379 /* Skip a certain number of bytes */
380 #define SKIP(bytes) \
384 /* Raw data - to end of frame */
385 #define OUT_BYTES_ALL(field) OUT_BYTES(field, offset+END_OF_FRAME-curoffset)
388 #define OUT_BYTES(field, bytes) \
390 proto_tree_add_bytes(tree,field, NullTVB,curoffset,bytes,\
391 (void *)&pd[curoffset]); \
394 /* Output a rx style string, up to a maximum length first
395 4 bytes - length, then char data */
396 #define OUT_STRING(field) \
404 tmp = g_malloc(i+1); \
405 memcpy(tmp, &pd[curoffset], i); \
407 proto_tree_add_string(tree, field, NullTVB, curoffset-4, i+4, \
411 proto_tree_add_string(tree, field, NullTVB, curoffset-4, 4, \
417 /* Output a fixed length vectorized string (each char is a 32 bit int) */
418 #define VECOUT(field, length) \
419 { char tmp[length+1]; \
422 TRUNC(length * sizeof(guint32));\
423 for (i=0; i<length; i++)\
425 tmp[i] = (char) GETINT();\
426 curoffset += sizeof(guint32);\
429 proto_tree_add_string(tree, field, NullTVB, soff, length, tmp);\
432 /* Skip the opcode */
433 #define SKIP_OPCODE() \
435 SKIP(sizeof(guint32)); \
438 /* Output a UBIK version code */
439 #define OUT_UBIKVERSION(label) \
440 { proto_tree *save, *ti; \
441 unsigned int epoch,counter; \
446 counter = GETINT(); \
450 ti = proto_tree_add_text(tree, NullTVB, curoffset, 3*4, \
451 "UBIK Version (%s): %u.%u", label, epoch, counter ); \
453 tree = proto_item_add_subtree(ti, ett_afs_ubikver); \
454 proto_tree_add_time(tree,hf_afs_ubik_version_epoch, NullTVB,curoffset-8, \
455 sizeof(guint32),&tv); \
456 proto_tree_add_uint(tree,hf_afs_ubik_version_counter, NullTVB,curoffset-4, \
457 sizeof(guint32),counter); \