2 * Routines for Web Cache Coordination Protocol dissection
3 * Jerry Talkington <jerryt@netapp.com>
5 * $Id: packet-wccp.c,v 1.1 1999/12/12 03:05:56 guy Exp $
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@unicom.net>
9 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 #ifdef HAVE_SYS_TYPES_H
32 # include <sys/types.h>
35 #ifdef HAVE_NETINET_IN_H
36 #include <netinet/in.h>
43 #define WCCP_HERE_I_AM 0x0007
44 #define WCCP_I_SEE_YOU 0x0008
45 #define WCCP_ASSIGN_BUCKET 0x0009
47 static const value_string wccp_types[] = {
48 { WCCP_HERE_I_AM, "WCCP_HERE_I_AM" },
49 { WCCP_I_SEE_YOU, "WCCP_I_SEE_YOU" },
50 { WCCP_ASSIGN_BUCKET, "WCCP_ASSIGN_BUCKET" },
54 static const value_string wccp_version_val[] = {
59 typedef struct _wccp_cache_info {
66 static guint32 proto_wccp = -1;
67 static guint32 ett_wccp = -1;
68 static guint32 ett_cache_count = -1;
69 static guint32 ett_cache_info = -1;
70 static guint32 ett_buckets = -1;
71 static guint32 hf_wccp_message_type = -1; /* the message type */
72 static guint32 hf_wccp_version = -1; /* protocol version */
73 static guint32 hf_hash_version = -1; /* the version of the hash */
74 static guint32 hf_change_num = -1; /* change number */
75 static guint32 hf_recvd_id = -1;
76 static guint32 hf_cache_ip = -1;
78 int wccp_bucket_info(guint8 bucket_info, proto_tree *bucket_tree, guint32 start, int offset);
81 dissect_wccp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
83 const u_char *data, *data_end;
84 proto_tree *wccp_tree = NULL;
85 proto_item *wccp_tree_item = NULL;
86 guint32 wccp_message_type = 0;
89 data_end = data + END_OF_FRAME;
91 if(check_col(fd, COL_PROTOCOL)) {
92 col_add_str(fd, COL_PROTOCOL, "WCCP");
95 wccp_message_type = pntohl(&pd[offset]);
97 if(check_col(fd, COL_INFO)) {
98 col_add_str(fd, COL_INFO, val_to_str(wccp_message_type, wccp_types, "Unknown WCCP message"));
102 guint32 wccp_version = 0;
104 wccp_tree_item = proto_tree_add_item_format(tree, proto_wccp, offset, (data_end - data),
105 NULL, "Web Cache Coordination Protocol");
107 wccp_tree = proto_item_add_subtree(wccp_tree_item, ett_wccp);
108 proto_tree_add_item(wccp_tree, hf_wccp_message_type , offset, sizeof(wccp_message_type), wccp_message_type);
109 offset += sizeof(wccp_message_type);
111 wccp_version = pntohl(&pd[offset]);
112 proto_tree_add_item(wccp_tree, hf_wccp_version, offset, sizeof(wccp_version), wccp_version);
113 offset += sizeof(wccp_version);
115 if (wccp_message_type == WCCP_HERE_I_AM) {
117 guint32 hash_version;
122 proto_tree *bucket_tree = NULL;
123 proto_item *bucket_item = NULL;
125 hash_version = pntohl(&pd[offset]);
126 proto_tree_add_item(wccp_tree, hf_hash_version, offset, sizeof(hash_version), hash_version);
127 offset += sizeof(hash_version);
129 bucket_item = proto_tree_add_text(wccp_tree, offset, 32, "Hash Information");
130 bucket_tree = proto_item_add_subtree(bucket_item, ett_buckets);
131 for(i = 0, n = 0; i < 32; i++) {
132 bucket_info = (guint32)pd[offset];
133 n = wccp_bucket_info(bucket_info, bucket_tree, n, offset);
134 offset += sizeof(bucket_info);
137 /* we only care about the first bit, the rest is just pad */
138 rsvd = (guint32 *)&pd[offset];
139 proto_tree_add_text(wccp_tree, offset, sizeof(rsvd), ( (*rsvd & (1<<31) ) ? "U: Historical" : "U: Current" ) );
140 offset += sizeof(rsvd);
142 recvd_id = pntohl(&pd[offset]);
143 proto_tree_add_item(wccp_tree, hf_recvd_id, offset, sizeof(recvd_id), recvd_id);
144 offset += sizeof(recvd_id); /* copy and paste is fun */
146 } else if (wccp_message_type == WCCP_I_SEE_YOU) {
147 guint32 change_num = 0;
148 guint32 recvd_id = 0;
149 guint32 cache_count = 0;
154 wccp_cache_info *cache_info;
155 proto_item *cache_count_item = NULL;
156 proto_item *cache_info_item = NULL;
157 proto_item *bucket_item = NULL;
158 proto_tree *cache_count_tree = NULL;
159 proto_tree *cache_info_tree = NULL;
160 proto_tree *bucket_tree = NULL;
163 change_num = pntohl(&pd[offset]);
164 proto_tree_add_item(wccp_tree, hf_change_num, offset, sizeof(change_num), change_num);
165 offset += sizeof(change_num);
167 recvd_id = pntohl(&pd[offset]);
168 proto_tree_add_item(wccp_tree, hf_recvd_id, offset, sizeof(recvd_id), recvd_id);
169 offset += sizeof(recvd_id);
171 cache_count = pntohl(&pd[offset]);
172 cache_count_item = proto_tree_add_text(wccp_tree, offset, sizeof(cache_count), "Number of caches: %i", cache_count);
173 offset += sizeof(cache_count);
175 cache_count_tree = proto_item_add_subtree(cache_count_item, ett_cache_count);
176 for(ccount = 0; ccount < cache_count; ccount++) {
177 cache_info = (wccp_cache_info *)&pd[offset];
178 cache_info_item = proto_tree_add_item(cache_count_tree, hf_cache_ip, offset, sizeof(cache_info->ip_addr), cache_info->ip_addr);
179 offset += sizeof(cache_info->ip_addr);
181 cache_info_tree = proto_item_add_subtree(cache_info_item, ett_cache_info);
183 proto_tree_add_text(cache_info_tree, offset, sizeof(cache_info->hash_rev), "Hash Revision: %i", cache_info->hash_rev);
184 offset += sizeof(cache_info->hash_rev);
185 bucket_item = proto_tree_add_text(cache_info_tree, offset, 32, "Hash Information");
186 bucket_tree = proto_item_add_subtree(bucket_item, ett_buckets);
189 for(i = 0, n = 0; i < 32; i++) {
190 bucket_info = (guint32)pd[offset];
191 n = wccp_bucket_info(bucket_info, bucket_tree, n, offset);
192 offset += sizeof(bucket_info);
194 proto_tree_add_text(cache_info_tree, offset, sizeof(cache_info->reserved), ( (cache_info->reserved & (1<<31) ) ? "U: Historical" : "U: Current" ) );
195 offset += sizeof(cache_info->reserved);
199 } else if (wccp_message_type == WCCP_ASSIGN_BUCKET) {
200 /* this hasn't been tested, since I don't have any traces with this in it. */
201 guint32 recvd_id = 0;
202 guint32 wc_count = 0;
208 proto_item *bucket_item;
210 proto_tree *bucket_tree;
212 recvd_id = pd[offset];
213 proto_tree_add_item(wccp_tree, hf_recvd_id, offset, sizeof(recvd_id), recvd_id);
214 offset += sizeof(recvd_id);
216 wc_count = pntohl(&pd[offset]);
217 ip_item = proto_tree_add_text(wccp_tree, offset, sizeof(wc_count), "Number of caches: %i", wc_count);
218 offset += sizeof(wc_count);
220 ip_tree = proto_item_add_subtree(ip_item, ett_cache_count);
221 for(i = 0; i < wc_count; i++) {
222 ip_addr = pd[offset];
223 proto_tree_add_item(ip_tree, hf_cache_ip, offset, sizeof(ip_addr), ip_addr);
224 offset += sizeof(ip_addr);
227 bucket_item = proto_tree_add_text(wccp_tree, offset, 32, "Bucket Assignments");
228 bucket_tree = proto_item_add_subtree(bucket_item, ett_buckets);
230 for(i = 0; i < 256; i++) {
231 bucket_info = pd[offset];
232 if(bucket_info != 0xff) {
233 cache_index = g_ntohs((guint16)bucket_info);
234 proto_tree_add_text(bucket_tree, offset, sizeof(bucket_info), "Bucket %i: Cache %i", i, bucket_info);
236 proto_tree_add_text(bucket_tree, offset, sizeof(bucket_info), "Bucket %i: Unassigned", i);
238 offset += sizeof(bucket_info);
248 * takes an integer representing a "Hash Information" bitmap, and spits out
249 * the corresponding proto_tree entries, returning the next bucket number.
252 wccp_bucket_info(guint8 bucket_info, proto_tree *bucket_tree, guint32 start, int offset)
256 for(i = 0; i < 8; i++) {
257 proto_tree_add_text(bucket_tree, offset, sizeof(bucket_info), "Bucket %3d: %s", start, (bucket_info & 1<<i ? "Assigned" : "Not Assigned") );
265 proto_register_wccp(void)
267 static gint *ett[] = {
273 static hf_register_info hf[] = {
274 { &hf_wccp_message_type,
275 { "WCCP Message Type", "wccp.message", FT_UINT32, BASE_DEC, VALS(wccp_types), 0x0,
276 "The WCCP message that was sent"}
279 { "WCCP Version", "wccp.version", FT_UINT32, BASE_DEC, VALS(wccp_version_val), 0x0,
283 { "Hash Revision", "wccp.hash_revision", FT_UINT32, BASE_DEC, 0x0, 0x0,
284 "The cache hash revision"}
287 { "Change Number", "wccp.change_num", FT_UINT32, BASE_DEC, 0x0, 0x0,
288 "The Web-Cache list entry change number"}
291 { "Received ID", "wccp.recvd_id", FT_UINT32, BASE_DEC, 0x0, 0x0,
292 "The number of I_SEE_YOU's that have been sent"}
295 { "Cache IP address", "wccp.cache.ip", FT_IPv4, BASE_NONE, NULL, 0x0,
296 "The IP address of a cache"}
302 proto_wccp = proto_register_protocol("Web Cache Coordination Protocol", "wccp");
303 proto_register_field_array(proto_wccp, hf, array_length(hf));
304 proto_register_subtree_array(ett, array_length(ett));