HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / dissectors / packet-wccp.c
bloba0700a20da6e0a1eddb5da7020d4b625ff2155b2
1 /* packet-wccp.c
2 * Routines for Web Cache Communication Protocol dissection
3 * Jerry Talkington <jtalkington@users.sourceforge.net>
5 * $Id$
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include "config.h"
28 #include <glib.h>
29 #include <epan/packet.h>
30 #include <epan/to_str.h>
31 #include <epan/wmem/wmem.h>
32 #include <epan/ipproto.h>
33 #include <epan/expert.h>
34 #include <epan/ipv6-utils.h>
35 #include <epan/ipv4.h>
36 #include "packet-wccp.h"
38 static int proto_wccp = -1;
39 static int hf_wccp_message_type = -1; /* the message type */
40 static int hf_wccp_version = -1; /* protocol version */
41 static int hf_message_header_version = -1;
42 static int hf_hash_revision = -1; /* the version of the hash */
43 static int hf_change_num = -1; /* change number */
44 static int hf_hash_flag = -1;
45 static int hf_hash_flag_u = -1;
46 static int hf_recvd_id = -1;
47 static int hf_wc_num = -1;
48 static int hf_wc_view_wc_num = -1;
49 static int hf_cache_ip = -1;
50 static int hf_message_header_length = -1;
51 static int hf_item_type = -1;
52 static int hf_item_length = -1;
53 static int hf_item_data = -1;
54 static int hf_security_info_option = -1;
55 static int hf_security_info_md5_checksum = -1;
56 static int hf_command_element_type = -1;
57 static int hf_command_element_length = -1;
58 static int hf_command_element_shutdown_ip = -1;
59 static int hf_service_info_type = -1;
60 static int hf_service_info_id_standard = -1;
61 static int hf_service_info_id_dynamic = -1;
62 static int hf_service_info_priority = -1;
63 static int hf_service_info_protocol = -1;
64 static int hf_service_info_flags = -1;
65 static int hf_service_info_flags_src_ip_hash = -1;
66 static int hf_service_info_flags_dest_ip_hash = -1;
67 static int hf_service_info_flags_src_port_hash = -1;
68 static int hf_service_info_flags_dest_port_hash = -1;
69 static int hf_service_info_flags_ports_defined = -1;
70 static int hf_service_info_flags_ports_source = -1;
71 static int hf_service_info_flags_redirect_only_protocol_0 = -1;
72 static int hf_service_info_flags_src_ip_alt_hash = -1;
73 static int hf_service_info_flags_dest_ip_alt_hash = -1;
74 static int hf_service_info_flags_src_port_alt_hash = -1;
75 static int hf_service_info_flags_dest_port_alt_hash = -1;
76 static int hf_service_info_source_port = -1;
77 static int hf_service_info_destination_port = -1;
78 static int hf_router_identity_ip = -1;
79 static int hf_router_identity_receive_id = -1;
80 static int hf_router_identity_send_to_ip = -1;
81 static int hf_router_identity_received_from_num = -1;
82 static int hf_web_cache_identity_ip = -1;
83 static int hf_web_cache_identity_hash_rev = -1;
84 static int hf_web_cache_identity_flags = -1;
85 static int hf_web_cache_identity_flag_hash_info = -1;
86 static int hf_web_cache_identity_flag_assign_type = -1;
87 static int hf_web_cache_identity_flag_version_request = -1;
88 static int hf_mask_value_set_element_value_element_num = -1;
89 static int hf_assignment_weight = -1;
90 static int hf_assignment_status = -1;
91 static int hf_assignment_key_ip = -1;
92 static int hf_assignment_key_change_num = -1;
93 static int hf_router_view_member_change_num = -1;
94 static int hf_router_router_num = -1;
95 static int hf_router_identity_router_ip = -1;
96 static int hf_wc_view_info_change_num = -1;
97 static int hf_wc_view_info_router_ip = -1;
98 static int hf_wc_view_info_wc_ip = -1;
99 static int hf_wc_view_router_num = -1;
100 static int hf_wc_identity_ip_address = -1;
101 static int hf_router_identity_received_from_ip = -1;
102 static int hf_router_assignment_element_change_num = -1;
103 static int hf_assignment_info_router_num = -1;
104 static int hf_hash_buckets_assignment_wc_num = -1;
105 static int hf_hash_buckets_assignment_wc_ip = -1;
106 static int hf_assignment_info_router_ip = -1;
107 static int hf_router_view_ip = -1;
108 static int hf_router_query_info_ip = -1;
109 static int hf_router_query_info_send_to_ip = -1;
110 static int hf_router_query_info_target_ip = -1;
111 static int hf_capability_element_type = -1;
112 static int hf_capability_element_length = -1;
113 static int hf_capability_info_value = -1;
114 static int hf_capability_forwarding_method_flag_gre = -1;
115 static int hf_capability_forwarding_method_flag_l2 = -1;
116 static int hf_capability_assignment_method_flag_hash = -1;
117 static int hf_capability_assignment_method_flag_mask = -1;
118 static int hf_capability_return_method_flag_gre = -1;
119 static int hf_capability_return_method_flag_l2 = -1;
120 static int hf_capability_transmit_t = -1;
121 static int hf_capability_transmit_t_upper_limit = -1;
122 static int hf_capability_transmit_t_lower_limit = -1;
123 static int hf_capability_timer_scale_timeout_scale = -1;
124 static int hf_capability_timer_scale_ra_timer_scale = -1;
125 static int hf_capability_timer_scale_timeout_scale_upper_limit = -1;
126 static int hf_capability_timer_scale_timeout_scale_lower_limit = -1;
127 static int hf_capability_timer_scale_ra_scale_upper_limit = -1;
128 static int hf_capability_timer_scale_ra_scale_lower_limit = -1;
129 static int hf_value_element_src_ip = -1;
130 static int hf_value_element_dest_ip = -1;
131 static int hf_value_element_src_port = -1;
132 static int hf_value_element_dest_port = -1;
133 static int hf_value_element_web_cache_ip = -1;
134 static int hf_mask_value_set_list_num_elements = -1;
135 static int hf_mask_element_src_ip = -1;
136 static int hf_mask_element_dest_ip = -1;
137 static int hf_mask_element_src_port = -1;
138 static int hf_mask_element_dest_port = -1;
139 static int hf_alt_assignment_info_assignment_type = -1;
140 static int hf_extended_assignment_data_type = -1;
141 static int hf_alt_assignment_info_assignment_length = -1;
142 static int hf_alt_assignment_map_assignment_type = -1;
143 static int hf_alt_assignment_map_assignment_length = -1;
144 static int hf_extended_assignment_data_length = -1;
145 static int hf_alt_assignment_info_num_routers = -1;
146 static int hf_alt_assignment_mask_value_set_element_num_wc_value_elements = -1;
147 static int hf_web_cache_value_element_wc_address = -1;
148 static int hf_web_cache_value_element_num_values = -1;
149 static int hf_alt_assignment_mask_value_set_list_num_elements = -1;
150 static int hf_address_table_family = -1;
151 static int hf_address_table_address_length = -1;
152 static int hf_address_table_length = -1;
153 static int hf_address_table_element = -1;
155 static gint ett_wccp = -1;
156 static gint ett_buckets = -1;
157 static gint ett_hash_assignment_buckets = -1;
158 static gint ett_mask_assignment_data_element = -1;
159 static gint ett_alternate_mask_assignment_data_element = -1;
160 static gint ett_extended_assigment_data_element = -1;
161 static gint ett_table_element = -1;
162 static gint ett_hash_flags = -1;
163 static gint ett_wc_identity_flags = -1;
164 static gint ett_cache_info = -1;
165 static gint ett_security_info = -1;
166 static gint ett_service_info = -1;
167 static gint ett_service_flags = -1;
168 static gint ett_service_info_ports = -1;
169 static gint ett_wc_view_info_router_element = -1;
170 static gint ett_router_identity_info = -1;
171 static gint ett_wc_identity_element = -1;
172 static gint ett_wc_identity_info = -1;
173 static gint ett_router_view_info = -1;
174 static gint ett_wc_view_info = -1;
175 static gint ett_router_assignment_element = -1;
176 static gint ett_hash_buckets_assignment_wc_element=-1;
177 static gint ett_hash_buckets_assignment_buckets=-1;
178 static gint ett_router_alt_assignment_element = -1;
179 static gint ett_router_assignment_info = -1;
180 static gint ett_query_info = -1;
181 static gint ett_capabilities_info = -1;
182 static gint ett_capability_element = -1;
183 static gint ett_capability_forwarding_method = -1;
184 static gint ett_capability_assignment_method = -1;
185 static gint ett_capability_return_method = -1;
186 static gint ett_capability_transmit_t = -1;
187 static gint ett_capability_timer_scale = -1;
188 static gint ett_alt_assignment_info = -1;
189 static gint ett_alt_assignment_map = -1;
190 static gint ett_address_table = -1;
191 static gint ett_assignment_map = -1;
192 static gint ett_command_extension = -1;
193 static gint ett_alternate_mask_value_set=-1;
194 static gint ett_alternate_mask_value_set_element=-1;
195 static gint ett_mv_set_list = -1;
196 static gint ett_mv_set_element = -1;
197 static gint ett_mv_set_value_list = -1;
198 static gint ett_alternate_mv_set_element_list = -1;
199 static gint ett_web_cache_value_element_list = -1;
200 static gint ett_alternate_mv_set_element = -1;
201 static gint ett_value_element = -1;
202 static gint ett_unknown_info = -1;
204 static expert_field ei_wccp_missing_security_info = EI_INIT;
205 static expert_field ei_wccp_missing_service_info = EI_INIT;
206 static expert_field ei_wccp_missing_wc_id_info = EI_INIT;
207 static expert_field ei_wccp_missing_router_id_info = EI_INIT;
208 static expert_field ei_wccp_missing_query_info = EI_INIT;
209 static expert_field ei_wccp_missing_wc_view_info = EI_INIT;
210 static expert_field ei_wccp_missing_rtr_view_info = EI_INIT;
211 static expert_field ei_wccp_contains_redirect_assignment = EI_INIT;
212 static expert_field ei_wccp_contains_router_id_info = EI_INIT;
213 static expert_field ei_wccp_contains_rtr_view_info = EI_INIT;
214 static expert_field ei_wccp_contains_query_info = EI_INIT;
215 static expert_field ei_wccp_contains_alt_assignment = EI_INIT;
216 static expert_field ei_wccp_contains_assign_map = EI_INIT;
217 static expert_field ei_wccp_contains_alt_assignment_map = EI_INIT;
218 static expert_field ei_wccp_contains_wc_id_info = EI_INIT;
219 static expert_field ei_wccp_contains_wc_view_info = EI_INIT;
220 static expert_field ei_wccp_contains_capabilities_info = EI_INIT;
221 static expert_field ei_wccp_contains_command_extension = EI_INIT;
222 static expert_field ei_wccp_missing_assignment = EI_INIT;
223 static expert_field ei_wccp_assignment_length_bad = EI_INIT;
224 static expert_field ei_wccp_length_bad = EI_INIT;
225 static expert_field ei_wccp_service_info_priority_nonzero = EI_INIT;
226 static expert_field ei_wccp_service_info_protocol_nonzero = EI_INIT;
227 static expert_field ei_wccp_router_identity_receive_id_zero = EI_INIT;
228 static expert_field ei_wccp_web_cache_identity_hash_rev_zero = EI_INIT;
229 static expert_field ei_wccp_address_table_family_unknown = EI_INIT;
230 static expert_field ei_wccp_capability_element_length = EI_INIT;
233 * At
235 * http://tools.ietf.org/html/draft-forster-wrec-wccp-v1-00
237 * is a copy of the now-expired Internet-Draft for WCCP 1.0.
239 * At
241 * http://tools.ietf.org/id/draft-wilson-wrec-wccp-v2-01.txt
243 * is an Internet-Draft for WCCP 2.0.
245 * http://tools.ietf.org/html/draft-mclaggan-wccp-v2rev1
247 * is the current draft for WCCP 2.01
251 /* This is NOT IANA assigned */
252 #define UDP_PORT_WCCP 2048
254 #define WCCPv1 4
255 #define WCCPv2 0x0200
256 #define WCCPv2r1 0x0201
257 #define WCCP_HERE_I_AM 7
258 #define WCCP_I_SEE_YOU 8
259 #define WCCP_ASSIGN_BUCKET 9
260 #define WCCP2_HERE_I_AM 10
261 #define WCCP2_I_SEE_YOU 11
262 #define WCCP2_REDIRECT_ASSIGN 12
263 #define WCCP2_REMOVAL_QUERY 13
265 static const value_string wccp_type_vals[] = {
266 { WCCP_HERE_I_AM, "1.0 Here I am" },
267 { WCCP_I_SEE_YOU, "1.0 I see you" },
268 { WCCP_ASSIGN_BUCKET, "1.0 Assign bucket" },
269 { WCCP2_HERE_I_AM, "2.0 Here I am" },
270 { WCCP2_I_SEE_YOU, "2.0 I see you" },
271 { WCCP2_REDIRECT_ASSIGN, "2.0 Redirect assign" },
272 { WCCP2_REMOVAL_QUERY, "2.0 Removal query" },
273 { 0, NULL }
276 static const value_string wccp_version_val[] = {
277 { WCCPv1, "1"},
278 { WCCPv2, "2"},
279 { WCCPv2r1, "2.01"},
280 { 0, NULL}
283 const true_false_string tfs_defined_not_defined = { "Defined", "Not defined" };
284 const true_false_string tfs_src_dest_port = { "Source port", "Destination port" };
285 const true_false_string tfs_redirect_protocol0 = { "Redirect only protocol 0 (IP)", "Redirect all traffic" };
286 const true_false_string tfs_historical_current = { "Historical", "Current" };
287 const true_false_string tfs_version_min_max = {"WCCP version set is maximum supported by CE", "WCCP version set is minimum supported by CE"};
289 static const value_string wccp_address_family_val[] = {
290 { 0, "Reserved" },
291 { 1, "IPv4" },
292 { 2, "IPv6" },
293 { 0, NULL }
297 #define WCCP2_HASH_ASSIGNMENT_TYPE 0
298 #define WCCP2_MASK_ASSIGNMENT_TYPE 1
299 #define WCCP2r1_ALT_MASK_ASSIGNMENT_TYPE 2
300 #define WCCP2r1_ASSIGNMENT_WEIGHT_STATUS 3
302 static const value_string assignment_type_vals[] = {
303 { WCCP2_HASH_ASSIGNMENT_TYPE, "Hash" },
304 { WCCP2_MASK_ASSIGNMENT_TYPE, "Mask" },
305 { WCCP2r1_ALT_MASK_ASSIGNMENT_TYPE, "WCCP2r1 Alternate Mask"},
306 { WCCP2r1_ASSIGNMENT_WEIGHT_STATUS, "WCCP2r1 Assignment Weight Status"},
307 { 0, NULL }
310 #define HASH_INFO_SIZE (4*(1+8+1))
312 #define WCCP2_SECURITY_INFO 0
313 #define WCCP2_SERVICE_INFO 1
314 #define WCCP2_ROUTER_ID_INFO 2
315 #define WCCP2_WC_ID_INFO 3
316 #define WCCP2_RTR_VIEW_INFO 4
317 #define WCCP2_WC_VIEW_INFO 5
318 #define WCCP2_REDIRECT_ASSIGNMENT 6
319 #define WCCP2_QUERY_INFO 7
320 #define WCCP2_CAPABILITIES_INFO 8
321 #define WCCP2_ALT_ASSIGNMENT 13
322 #define WCCP2_ASSIGN_MAP 14
323 #define WCCP2_COMMAND_EXTENSION 15
324 /* WCCP 2 r1 additions: */
325 #define WCCP2r1_ALT_ASSIGNMENT_MAP 16
326 #define WCCP2r1_ADDRESS_TABLE 17
328 static const value_string info_type_vals[] = {
329 { WCCP2_SECURITY_INFO, "Security Info" },
330 { WCCP2_SERVICE_INFO, "Service Info" },
331 { WCCP2_ROUTER_ID_INFO, "Router Identity Info" },
332 { WCCP2_WC_ID_INFO, "Web-Cache Identity Info" },
333 { WCCP2_RTR_VIEW_INFO, "Router View Info" },
334 { WCCP2_WC_VIEW_INFO, "Web-Cache View Info" },
335 { WCCP2_REDIRECT_ASSIGNMENT, "Assignment Info" },
336 { WCCP2_QUERY_INFO, "Router Query Info" },
337 { WCCP2_CAPABILITIES_INFO, "Capabilities Info" },
338 { WCCP2_ALT_ASSIGNMENT, "Alternate Assignment" },
339 { WCCP2_ASSIGN_MAP, "Assignment Map" },
340 { WCCP2_COMMAND_EXTENSION, "Command Extension" },
341 { WCCP2r1_ALT_ASSIGNMENT_MAP, "Alternative Assignment Map" },
342 { WCCP2r1_ADDRESS_TABLE, "Address Table" },
343 { 0, NULL }
346 const value_string service_id_vals[] = {
347 { 0x00, "HTTP" },
348 { 0, NULL }
351 typedef struct capability_flag {
352 guint32 value;
353 const char *short_name;
354 int* phf;
355 } capability_flag;
360 #define WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_HASH 0
361 #define WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_MASK 1
362 #define WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_NOT_PRESENT 2
363 #define WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_EXTENDED 3
365 static const value_string wccp_web_cache_assignment_data_type_val[] = {
366 { WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_HASH , "Hash Assignment Data Element"},
367 { WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_MASK , "Mask Assignment Data Element"},
368 { WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_NOT_PRESENT , "Assignment Data Element Not Present"},
369 { WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_EXTENDED , "Extended Assignment Data Element"},
370 { 0, NULL }
373 #define WCCP2_FORWARDING_METHOD 0x01
374 #define WCCP2_ASSIGNMENT_METHOD 0x02
375 #define WCCP2_PACKET_RETURN_METHOD 0x03
376 #define WCCP2_TRANSMIT_T 0x04
377 #define WCCP2_TIMER_SCALE 0x05
379 static const value_string capability_type_vals[] = {
380 { WCCP2_FORWARDING_METHOD, "Forwarding Method" },
381 { WCCP2_ASSIGNMENT_METHOD, "Assignment Method" },
382 { WCCP2_PACKET_RETURN_METHOD, "Packet Return Method" },
383 { WCCP2_TRANSMIT_T, "Transmit_t Message interval values"},
384 { WCCP2_TIMER_SCALE, "Timer_scale Timeout scale values"},
385 { 0, NULL }
389 /* with version 2.01 we now have a address table which is possibly present */
391 typedef struct wccp_address_table {
392 gboolean in_use;
393 gint16 family;
394 gint16 version;
395 guint16 table_length;
396 guint32 *table_ipv4;
397 struct e_in6_addr *table_ipv6;
398 } wccp_address_table;
401 wccp_address_table wccp_wccp_address_table;
403 static guint dissect_hash_data(tvbuff_t *tvb, int offset,
404 proto_tree *wccp_tree);
405 static guint dissect_web_cache_list_entry(tvbuff_t *tvb, int offset,
406 int idx, proto_tree *wccp_tree);
407 static int wccp_bucket_info(guint8 bucket_info, proto_tree *bucket_tree,
408 guint32 start, tvbuff_t *tvb, int offset);
409 static gchar *bucket_name(guint8 bucket);
410 static guint16 dissect_wccp2_header(tvbuff_t *tvb, int offset,
411 proto_tree *wccp_tree);
412 static void dissect_wccp2_info(tvbuff_t *tvb, int offset, guint16 length,
413 packet_info *pinfo, proto_tree *wccp_tree, guint32 wccp_message_type);
415 /* WCCP 2r1 IPv6 utlility functions */
416 static void find_wccp_address_table(tvbuff_t *tvb, int offset, guint16 length,
417 packet_info *pinfo _U_, proto_tree *wccp_tree _U_);
418 /* The V2 dissectors will return the remaining length of the packet
419 and a negative number if there are missing bytes to finish the
420 dissection */
421 static gint dissect_wccp2_security_info(tvbuff_t *tvb, int offset, gint lengreth,
422 packet_info *pinfo _U_, proto_tree *info_tree);
423 static gint dissect_wccp2_service_info(tvbuff_t *tvb, int offset, gint length,
424 packet_info *pinfo, proto_tree *info_tree);
425 static gint dissect_wccp2r1_address_table_info(tvbuff_t *tvb, int offset,
426 int length, packet_info *pinfo, proto_tree *info_tree);
427 static gint dissect_wccp2_router_identity_info(tvbuff_t *tvb, int offset, gint length,
428 packet_info *pinfo _U_, proto_tree *info_tree);
429 static gint dissect_wccp2_wc_identity_info(tvbuff_t *tvb, int offset, gint length,
430 packet_info *pinfo _U_, proto_tree *info_tree);
431 static gint dissect_wccp2_router_view_info(tvbuff_t *tvb, int offset, gint length,
432 packet_info *pinfo _U_, proto_tree *info_tree);
433 static gint dissect_wccp2_web_cache_view_info(tvbuff_t *tvb, int offset, gint length,
434 packet_info *pinfo _U_, proto_tree *info_tree);
435 static gint dissect_wccp2_assignment_info(tvbuff_t *tvb, int offset, gint length,
436 packet_info *pinfo _U_, proto_tree *info_tree);
437 static gint dissect_wccp2_hash_buckets_assignment_element(tvbuff_t *tvb, int offset, gint length,
438 packet_info *pinfo, proto_tree *info_tree);
439 static gboolean dissect_wccp2_router_query_info(tvbuff_t *tvb, int offset, gint length,
440 packet_info *pinfo _U_, proto_tree *info_tree);
441 static gint dissect_wccp2_capability_info(tvbuff_t *tvb, int offset, gint length,
442 packet_info *pinfo _U_, proto_tree *info_tree);
443 static gint dissect_wccp2_alternate_assignment_info(tvbuff_t *tvb, int offset, gint length,
444 packet_info *pinfo, proto_tree *info_tree);
445 static gint dissect_wccp2_hash_assignment_info(tvbuff_t *tvb, int offset, gint length,
446 packet_info *pinfo _U_, proto_tree *info_tree);
447 static gint dissect_wccp2_assignment_map(tvbuff_t *tvb, int offset,
448 int length, packet_info *pinfo _U_, proto_tree *info_tree);
449 static gint dissect_wccp2r1_alt_assignment_map_info(tvbuff_t *tvb, int offset,
450 int length, packet_info *pinfo, proto_tree *info_tree);
451 static gint dissect_wccp2_command_extension(tvbuff_t *tvb, int offset,
452 int length, packet_info *pinfo _U_, proto_tree *info_tree);
453 static void dissect_wccp2_router_identity_element(tvbuff_t *tvb, int offset, packet_info *pinfo,
454 proto_tree *tree);
455 static gint dissect_wccp2_web_cache_identity_element(tvbuff_t *tvb, int offset, gint length, packet_info *pinfo,
456 proto_tree *info_tree);
457 static gint dissect_wccp2_hash_assignment_data_element(tvbuff_t *tvb, int offset, gint length, packet_info *pinfo,
458 proto_tree *info_tree);
459 static gint dissect_wccp2_mask_assignment_data_element(tvbuff_t *tvb, int offset, gint length, packet_info *pinfo,
460 proto_tree *info_tree) ;
461 static gint dissect_wccp2_alternate_mask_assignment_data_element(tvbuff_t *tvb, int offset, gint length, packet_info *pinfo,
462 proto_tree *info_tree);
463 static gint dissect_wccp2_assignment_weight_and_status_element(tvbuff_t *tvb, int offset, gint length, packet_info *pinfo,
464 proto_tree *info_tree);
465 static gint dissect_wccp2_extended_assignment_data_element(tvbuff_t *tvb, int offset, gint length, packet_info *pinfo,
466 proto_tree *info_tree);
467 static gint dissect_wccp2_assignment_key_element(tvbuff_t *tvb, int offset, gint length, packet_info *pinfo,
468 proto_tree *info_tree);
469 static void dissect_wccp2_router_assignment_element(tvbuff_t *tvb, int offset, gint length,
470 packet_info *pinfo, proto_tree *info_tree) ;
471 static gint dissect_wccp2_capability_element(tvbuff_t *tvb, int offset, gint length,
472 packet_info *pinfo _U_, proto_tree *info_tree);
473 static gint dissect_wccp2_mask_value_set_list(tvbuff_t *tvb, int offset,
474 int length, packet_info *pinfo, proto_tree *info_tree);
476 /* Utility functions */
477 static gint dissect_wccp2_mask_value_set_element(tvbuff_t *tvb, int offset,
478 gint length, int idx, packet_info *pinfo, proto_tree *info_tree);
479 static gint dissect_wccp2_mask_element(tvbuff_t *tvb, int offset,
480 gint length, packet_info *pinfo, proto_tree *info_tree);
481 static gint dissect_wccp2_value_element(tvbuff_t *tvb, int offset,
482 gint length, int idx, packet_info *pinfo, proto_tree *info_tree);
483 static gint dissect_wccp2_alternate_mask_value_set_list(tvbuff_t *tvb, int offset,
484 gint length, packet_info *pinfo _U_, proto_tree *info_tree);
485 static gint dissect_wccp2_alternate_mask_value_set_element(tvbuff_t *tvb, int offset, gint length, guint el_index, packet_info *pinfo, proto_tree *info_tree);
486 static gint dissect_wccp2_web_cache_value_element(tvbuff_t *tvb, int offset,
487 gint length, packet_info *pinfo, proto_tree *info_tree);
488 static gchar *assignment_bucket_name(guint8 bucket);
489 static void dissect_32_bit_capability_flags(tvbuff_t *tvb, int curr_offset,
490 guint16 capability_val_len, gint ett, const capability_flag *flags,
491 proto_tree *element_tree, proto_item *header);
492 static void dissect_transmit_t_capability(tvbuff_t *tvb, proto_item *te, int curr_offset,
493 guint16 capability_val_len, gint ett, proto_tree *element_tree);
494 static void dissect_timer_scale_capability(tvbuff_t *tvb, int curr_offset,
495 guint16 capability_val_len, gint ett, proto_tree *element_tree);
501 * In WCCP 2.01 addresses are encoded to support IPv6 with 32 bit fields
503 * handle the decoding
506 static void
507 find_wccp_address_table(tvbuff_t *tvb, int offset, guint16 length,
508 packet_info *pinfo _U_, proto_tree *wccp_tree _U_)
510 guint16 type;
511 guint16 item_length;
513 /* first clean up: */
514 wccp_wccp_address_table.in_use = FALSE;
515 wccp_wccp_address_table.family = -1;
516 wccp_wccp_address_table.version = -1;
517 wccp_wccp_address_table.table_length = 0;
518 wccp_wccp_address_table.table_ipv4 = (guint32 *) NULL;
519 wccp_wccp_address_table.table_ipv6 = (struct e_in6_addr *)NULL;
521 while (length >= 4) {
522 type = tvb_get_ntohs(tvb, offset);
523 item_length = tvb_get_ntohs(tvb, offset+2);
525 if (item_length > tvb_length_remaining(tvb, offset))
526 return;
528 if (type == WCCP2r1_ADDRESS_TABLE)
530 dissect_wccp2r1_address_table_info(tvb, offset+4, item_length, NULL, NULL);
531 /* no need to decode the rest */
532 return;
535 /* check if we _can_ advance */
536 if (length < (item_length+4))
537 return;
539 offset = offset + item_length + 4;
540 length = length - item_length - 4;
545 /* This function prints the IP or the encoded IP if the table exists */
547 /* at most an IPv6 IP: see
548 http://stackoverflow.com/questions/166132/maximum-length-of-the-textual-representation-of-an-ipv6-address
550 39 = 8 groups of 4 digits with 7 : characters
554 45 = IPv4 tunnel features: 0000:0000:0000:0000:0000:0000:192.168.0.1
557 /* problem here is that the IP is in network byte order for IPv4
558 we need to fix that
561 static void wccp_fmt_ipadddress(gchar *buffer, guint32 host_addr)
563 /* are we using an address table? */
564 if (! wccp_wccp_address_table.in_use)
566 /* no return the IPv4 IP */
567 /* first fix the byte order */
568 guint addr= GUINT32_SWAP_LE_BE(host_addr);
570 ip_to_str_buf( (guint8 *) &addr, buffer, ITEM_LABEL_LENGTH);
571 return;
573 else
575 /* we need to decode the encoded address: */
576 guint16 reserv = (host_addr & 0xFF00) >> 16;
577 guint16 addr_index = (host_addr & 0x00FF);
579 if (reserv != 0) {
580 g_snprintf(buffer, ITEM_LABEL_LENGTH, "INVALID: reserved part non zero");
581 return;
584 /* now check if it's IPv4 or IPv6 we need to print */
585 switch (wccp_wccp_address_table.family) {
586 case 1:
587 /* IPv4 */
589 /* special case: index 0 -> undefined IP */
590 if (addr_index == 0) {
591 g_snprintf(buffer, ITEM_LABEL_LENGTH, "0.0.0.0");
592 return;
594 /* are we be beyond the end of the table? */
595 if (addr_index > wccp_wccp_address_table.table_length) {
596 g_snprintf(buffer, ITEM_LABEL_LENGTH, "INVALID IPv4 index: %d > %d",
597 addr_index, wccp_wccp_address_table.table_length);
598 return;
601 /* ok get the IP */
602 if (wccp_wccp_address_table.table_ipv4 != NULL) {
603 ip_to_str_buf( (guint8 *) &(wccp_wccp_address_table.table_ipv4[addr_index-1]), buffer, ITEM_LABEL_LENGTH);
604 return;
606 else {
607 g_snprintf(buffer, ITEM_LABEL_LENGTH, "INVALID IPv4 table empty!");
608 return;
610 break;
611 case 2:
612 /* IPv6 */
613 /* special case: index 0 -> undefined IP */
614 if (addr_index == 0) {
615 g_snprintf(buffer, ITEM_LABEL_LENGTH, "::");
616 return;
619 /* are we be beyond the end of the table? */
620 if (addr_index > wccp_wccp_address_table.table_length) {
621 g_snprintf(buffer, ITEM_LABEL_LENGTH, "INVALID IPv6 index: %d > %d",
622 addr_index, wccp_wccp_address_table.table_length);
623 return;
626 /* ok get the IP */
627 if (wccp_wccp_address_table.table_ipv6 != NULL) {
628 ip6_to_str_buf(&(wccp_wccp_address_table.table_ipv6[addr_index-1]), buffer);
629 return;
631 else {
632 g_snprintf(buffer, ITEM_LABEL_LENGTH, "INVALID IPv6 table empty!");
633 return;
635 break;
636 default:
637 g_snprintf(buffer, ITEM_LABEL_LENGTH, "INVALID IP family");
638 return;
644 #define WCCP_IP_MAX_LENGTH (MAX_IP_STR_LEN > 46 ? MAX_IP_STR_LEN : 46)
647 static const gchar * decode_wccp_encoded_address(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *info_tree _U_)
649 gchar *buffer;
650 guint32 host_addr;
652 buffer= (char *) wmem_alloc(wmem_packet_scope(), WCCP_IP_MAX_LENGTH+1);
653 host_addr = tvb_get_ntohl(tvb,offset);
655 wccp_fmt_ipadddress(buffer, host_addr);
656 return buffer;
659 static int
660 dissect_wccp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
662 int offset = 0;
663 proto_tree *wccp_tree = NULL;
664 proto_item *wccp_tree_item;
665 guint32 wccp_message_type;
666 guint16 length;
667 guint32 cache_count;
668 guint32 ipaddr;
669 guint i;
671 wccp_message_type = tvb_get_ntohl(tvb, offset);
673 /* Check if this is really a WCCP message */
674 if (try_val_to_str(wccp_message_type, wccp_type_vals) == NULL)
675 return 0;
677 col_set_str(pinfo->cinfo, COL_PROTOCOL, "WCCP");
679 col_add_str(pinfo->cinfo, COL_INFO, val_to_str(wccp_message_type,
680 wccp_type_vals, "Unknown WCCP message (%u)"));
682 wccp_tree_item = proto_tree_add_item(tree, proto_wccp, tvb, offset, -1, ENC_NA);
683 wccp_tree = proto_item_add_subtree(wccp_tree_item, ett_wccp);
685 proto_tree_add_uint(wccp_tree, hf_wccp_message_type, tvb, offset, 4, wccp_message_type);
686 offset += 4;
688 switch (wccp_message_type) {
690 case WCCP_HERE_I_AM:
691 proto_tree_add_item(wccp_tree, hf_wccp_version, tvb,
692 offset, 4, ENC_BIG_ENDIAN);
693 offset += 4;
694 offset = dissect_hash_data(tvb, offset, wccp_tree);
695 proto_tree_add_item(wccp_tree, hf_recvd_id, tvb, offset,
696 4, ENC_BIG_ENDIAN);
697 /*offset += 4;*/
698 break;
700 case WCCP_I_SEE_YOU:
701 proto_tree_add_item(wccp_tree, hf_wccp_version, tvb,
702 offset, 4, ENC_BIG_ENDIAN);
703 offset += 4;
704 proto_tree_add_item(wccp_tree, hf_change_num, tvb, offset,
705 4, ENC_BIG_ENDIAN);
706 offset += 4;
707 proto_tree_add_item(wccp_tree, hf_recvd_id, tvb, offset,
708 4, ENC_BIG_ENDIAN);
709 offset += 4;
710 cache_count = tvb_get_ntohl(tvb, offset);
711 proto_tree_add_uint(wccp_tree, hf_wc_num, tvb, offset, 4, cache_count);
712 offset += 4;
713 for (i = 0; i < cache_count; i++) {
714 offset = dissect_web_cache_list_entry(tvb, offset, i,
715 wccp_tree);
717 break;
719 case WCCP_ASSIGN_BUCKET:
721 * This hasn't been tested, since I don't have any
722 * traces with this in it.
724 * The V1 spec claims that this does, indeed,
725 * have a Received ID field after the type,
726 * rather than a Version field.
728 proto_tree_add_item(wccp_tree, hf_recvd_id, tvb, offset,
729 4, ENC_BIG_ENDIAN);
730 offset += 4;
731 cache_count = tvb_get_ntohl(tvb, offset);
732 proto_tree_add_uint(wccp_tree, hf_wc_num, tvb, offset, 4, cache_count);
733 offset += 4;
734 for (i = 0; i < cache_count; i++) {
735 ipaddr = tvb_get_ipv4(tvb, offset);
736 proto_tree_add_ipv4_format(wccp_tree,
737 hf_cache_ip, tvb, offset, 4,
738 ipaddr,
739 "Web Cache %d IP Address: %s", i,
740 ip_to_str((guint8 *)&ipaddr));
741 offset += 4;
743 for (i = 0; i < 256; i += 4) {
744 proto_tree_add_text(wccp_tree, tvb, offset, 4,
745 "Buckets %d - %d: %10s %10s %10s %10s",
746 i, i + 3,
747 bucket_name(tvb_get_guint8(tvb, offset)),
748 bucket_name(tvb_get_guint8(tvb, offset+1)),
749 bucket_name(tvb_get_guint8(tvb, offset+2)),
750 bucket_name(tvb_get_guint8(tvb, offset+3)));
751 offset += 4;
753 break;
755 case WCCP2_HERE_I_AM:
756 case WCCP2_I_SEE_YOU:
757 case WCCP2_REMOVAL_QUERY:
758 case WCCP2_REDIRECT_ASSIGN:
759 default: /* assume unknown packets are v2 */
760 length = dissect_wccp2_header(tvb, offset, wccp_tree);
761 offset += 4;
762 dissect_wccp2_info(tvb, offset, length, pinfo, wccp_tree, wccp_message_type);
763 break;
766 return tvb_length(tvb);
769 static guint
770 dissect_hash_data(tvbuff_t *tvb, int offset, proto_tree *wccp_tree)
772 proto_item *bucket_item;
773 proto_tree *bucket_tree;
774 proto_item *tf;
775 proto_tree *field_tree;
776 int i;
777 guint8 bucket_info;
778 int n;
780 proto_tree_add_item(wccp_tree, hf_hash_revision, tvb, offset, 4,
781 ENC_BIG_ENDIAN);
782 offset += 4;
784 bucket_item = proto_tree_add_text(wccp_tree, tvb, offset, 32,
785 "Hash information");
786 bucket_tree = proto_item_add_subtree(bucket_item, ett_buckets);
788 for (i = 0, n = 0; i < 32; i++) {
789 bucket_info = tvb_get_guint8(tvb, offset);
790 n = wccp_bucket_info(bucket_info, bucket_tree, n, tvb, offset);
791 offset += 1;
793 tf = proto_tree_add_item(wccp_tree, hf_hash_flag, tvb, offset, 4, ENC_BIG_ENDIAN);
794 field_tree = proto_item_add_subtree(tf, ett_hash_flags);
795 proto_tree_add_item(field_tree, hf_hash_flag_u, tvb, offset, 4, ENC_BIG_ENDIAN);
796 offset += 4;
797 return offset;
800 static guint
801 dissect_web_cache_list_entry(tvbuff_t *tvb, int offset, int idx,
802 proto_tree *wccp_tree)
804 proto_item *tl;
805 proto_tree *list_entry_tree;
807 tl = proto_tree_add_text(wccp_tree, tvb, offset, 4 + HASH_INFO_SIZE,
808 "Web-Cache List Entry(%d)", idx);
809 list_entry_tree = proto_item_add_subtree(tl, ett_cache_info);
810 proto_tree_add_item(list_entry_tree, hf_cache_ip, tvb, offset, 4,
811 ENC_BIG_ENDIAN);
812 offset += 4;
813 offset = dissect_hash_data(tvb, offset, list_entry_tree);
814 return offset;
818 * wccp_bucket_info()
819 * takes an integer representing a "Hash Information" bitmap, and spits out
820 * the corresponding proto_tree entries, returning the next bucket number.
822 static int
823 wccp_bucket_info(guint8 bucket_info, proto_tree *bucket_tree, guint32 start,
824 tvbuff_t *tvb, int offset)
826 guint32 i;
828 for(i = 0; i < 8; i++) {
829 proto_tree_add_text(bucket_tree, tvb, offset, sizeof(bucket_info), "Bucket %3d: %s", start, (bucket_info & 1<<i ? "Assigned" : "Not Assigned") );
830 start++;
832 return(start);
835 static gchar *
836 bucket_name(guint8 bucket)
838 if (bucket == 0xff) {
839 return (gchar *) "Unassigned";
840 } else {
841 return wmem_strdup_printf(wmem_packet_scope(), "%u", bucket);
846 /* 5.5 WCCP Message Header */
847 static guint16
848 dissect_wccp2_header(tvbuff_t *tvb, int offset, proto_tree *wccp_tree)
850 guint16 length;
852 proto_tree_add_item(wccp_tree, hf_message_header_version, tvb, offset, 2,
853 ENC_BIG_ENDIAN);
854 offset += 2;
855 length = tvb_get_ntohs(tvb, offset);
856 proto_tree_add_uint(wccp_tree, hf_message_header_length, tvb, offset, 2, length);
857 return length;
861 static void
862 dissect_wccp2_info(tvbuff_t *tvb, int offset, guint16 length,
863 packet_info *pinfo, proto_tree *wccp_tree,
864 guint32 message_type)
866 guint16 type;
867 guint16 item_length;
868 proto_item *tf;
869 proto_tree *info_tree;
870 gint ett;
871 gint (*dissector)(tvbuff_t *, int, int, packet_info *, proto_tree *);
873 /* check if all required fields are there */
874 gboolean wccp2_security_info;
875 gboolean wccp2_service_info;
876 gboolean wccp2_router_id_info;
877 gboolean wccp2_wc_id_info;
878 gboolean wccp2_rtr_view_info;
879 gboolean wccp2_wc_view_info;
880 gboolean wccp2_redirect_assignment;
881 gboolean wccp2_query_info;
882 gboolean wccp2_capabilities_info;
883 gboolean wccp2_alt_assignment;
884 gboolean wccp2_assign_map;
885 gboolean wccp2_command_extension;
886 gboolean wccp2r1_alt_assignment_map;
888 wccp2_security_info=FALSE;
889 wccp2_service_info=FALSE;
890 wccp2_router_id_info=FALSE;
891 wccp2_wc_id_info=FALSE;
892 wccp2_rtr_view_info=FALSE;
893 wccp2_wc_view_info=FALSE;
894 wccp2_redirect_assignment=FALSE;
895 wccp2_query_info=FALSE;
896 wccp2_capabilities_info=FALSE;
897 wccp2_alt_assignment=FALSE;
898 wccp2_assign_map=FALSE;
899 wccp2_command_extension=FALSE;
900 wccp2r1_alt_assignment_map=FALSE;
902 /* ugly hack: we first need to check for the address table
903 compnent, otherwise we cannot print the IP's.
905 find_wccp_address_table(tvb,offset,length,pinfo,wccp_tree);
907 while (length != 0) {
909 if (length < 4) {
910 tf = proto_tree_add_text(wccp_tree, tvb, offset, length,
911 "Invalid WCCP Type/Length values");
913 expert_add_info_format(pinfo, tf, &ei_wccp_length_bad,
914 "The packet only has %d bytes left. That is not enough for a WCCP item type and length.",
915 length);
916 break;
919 type = tvb_get_ntohs(tvb, offset);
920 item_length = tvb_get_ntohs(tvb, offset+2);
923 if (item_length > tvb_length_remaining(tvb, offset)) {
924 tf = proto_tree_add_text(wccp_tree, tvb, offset, length,
925 "Excessive WCCP Length values");
926 expert_add_info_format(pinfo, tf, &ei_wccp_length_bad,
927 "The length of the item is %d but there are only %d bytes remaining in the packet, I counted %d remaining",
928 item_length, tvb_length_remaining(tvb, offset), length);
929 break;
931 switch (type) {
933 case WCCP2_SECURITY_INFO:
934 wccp2_security_info=TRUE;
935 ett = ett_security_info;
936 dissector = dissect_wccp2_security_info;
937 break;
939 case WCCP2_SERVICE_INFO:
940 wccp2_service_info=TRUE;
941 ett = ett_service_info;
942 dissector = dissect_wccp2_service_info;
943 break;
945 case WCCP2_ROUTER_ID_INFO:
946 wccp2_router_id_info=TRUE;
947 ett = ett_router_identity_info;
948 dissector = dissect_wccp2_router_identity_info;
949 break;
951 case WCCP2_WC_ID_INFO:
952 wccp2_wc_id_info=TRUE;
953 ett = ett_wc_identity_info;
954 dissector = dissect_wccp2_wc_identity_info;
955 break;
957 case WCCP2_RTR_VIEW_INFO:
958 wccp2_rtr_view_info=TRUE;
959 ett = ett_router_view_info;
960 dissector = dissect_wccp2_router_view_info;
961 break;
963 case WCCP2_WC_VIEW_INFO:
964 wccp2_wc_view_info=TRUE;
965 ett = ett_wc_view_info;
966 dissector = dissect_wccp2_web_cache_view_info;
967 break;
969 case WCCP2_REDIRECT_ASSIGNMENT:
970 wccp2_redirect_assignment=TRUE;
971 ett = ett_router_assignment_info;
972 dissector = dissect_wccp2_assignment_info;
973 break;
975 case WCCP2_QUERY_INFO:
976 wccp2_query_info=TRUE;
977 ett = ett_query_info;
978 dissector = dissect_wccp2_router_query_info;
979 break;
981 case WCCP2_CAPABILITIES_INFO:
982 wccp2_capabilities_info=TRUE;
983 ett = ett_capabilities_info;
984 dissector = dissect_wccp2_capability_info;
985 break;
987 case WCCP2_ALT_ASSIGNMENT:
988 wccp2_alt_assignment=TRUE;
989 ett = ett_alt_assignment_info;
990 dissector = dissect_wccp2_alternate_assignment_info;
991 break;
993 case WCCP2r1_ALT_ASSIGNMENT_MAP:
994 wccp2r1_alt_assignment_map=TRUE;
995 ett = ett_alt_assignment_map;
996 dissector = dissect_wccp2r1_alt_assignment_map_info;
997 break;
999 case WCCP2r1_ADDRESS_TABLE:
1000 ett = ett_address_table;
1001 dissector = dissect_wccp2r1_address_table_info;
1002 break;
1004 case WCCP2_ASSIGN_MAP:
1005 wccp2_assign_map=TRUE;
1006 ett = ett_assignment_map;
1007 dissector = dissect_wccp2_assignment_map;
1008 break;
1009 case WCCP2_COMMAND_EXTENSION:
1010 wccp2_command_extension=TRUE;
1011 ett = ett_command_extension;
1012 dissector = dissect_wccp2_command_extension;
1013 break;
1015 default:
1016 ett = ett_unknown_info;
1017 dissector = NULL;
1018 break;
1021 tf = proto_tree_add_text(wccp_tree, tvb, offset, item_length + 4, "%s",
1022 val_to_str(type, info_type_vals, "Unknown info type (%u)"));
1023 info_tree = proto_item_add_subtree(tf, ett);
1024 proto_tree_add_item(info_tree, hf_item_type, tvb, offset, 2, ENC_BIG_ENDIAN);
1025 proto_tree_add_item(info_tree, hf_item_length, tvb, offset+2, 2, ENC_BIG_ENDIAN);
1027 offset += 4;
1028 length -= 4;
1030 if (length < item_length) {
1031 expert_add_info_format(pinfo, tf, &ei_wccp_length_bad,
1032 "The item has length %d but the remaining WCCP data is only %d long",
1033 item_length,
1034 length);
1037 if (dissector != NULL) {
1038 gint remaining_item_length = (*dissector)(tvb, offset, item_length, pinfo, info_tree);
1040 /* warn if we left bytes */
1041 if (remaining_item_length > 0)
1042 expert_add_info_format(pinfo, tf, &ei_wccp_length_bad,
1043 "The dissector left %d bytes undecoded",
1044 remaining_item_length);
1046 /* error if we needed more bytes */
1047 if (remaining_item_length < 0)
1048 expert_add_info_format(pinfo, tf, &ei_wccp_length_bad,
1049 "The dissector needed %d more bytes to decode the packet, but the item is not that long",
1050 remaining_item_length);
1052 /* we assume that the item length is correct and jump forward */
1053 } else {
1054 proto_tree_add_item(info_tree, hf_item_data, tvb, offset, item_length, ENC_NA);
1056 /* avoid looping forever */
1057 if (length < item_length)
1058 return;
1060 offset += item_length;
1062 /* should no happen....*/
1063 DISSECTOR_ASSERT( ( (signed int) length - item_length) >= 0);
1064 length -= item_length;
1068 /* we're done. Check if we got all the required components */
1070 switch (message_type) {
1071 case WCCP2_HERE_I_AM:
1072 if (!wccp2_security_info)
1073 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_security_info);
1074 if (!wccp2_service_info)
1075 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_service_info);
1076 if (wccp2_router_id_info)
1077 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_router_id_info);
1078 if (!wccp2_wc_id_info)
1079 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_wc_id_info);
1080 if (wccp2_rtr_view_info)
1081 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_rtr_view_info);
1082 if (!wccp2_wc_view_info)
1083 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_wc_view_info);
1084 if (wccp2_redirect_assignment)
1085 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_redirect_assignment);
1086 if (wccp2_query_info)
1087 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_query_info);
1088 if (wccp2_alt_assignment)
1089 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_alt_assignment);
1090 if (wccp2_assign_map)
1091 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_assign_map);
1092 if (wccp2r1_alt_assignment_map)
1093 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_alt_assignment_map);
1094 break;
1095 case WCCP2_I_SEE_YOU:
1096 if (!wccp2_security_info)
1097 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_security_info);
1098 if (!wccp2_service_info)
1099 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_service_info);
1100 if (!wccp2_router_id_info)
1101 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_router_id_info);
1102 if (wccp2_wc_id_info)
1103 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_wc_id_info);
1104 if (!wccp2_rtr_view_info)
1105 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_rtr_view_info);
1106 if (wccp2_wc_view_info)
1107 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_wc_view_info);
1108 if (wccp2_redirect_assignment)
1109 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_redirect_assignment);
1110 if (wccp2_query_info)
1111 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_query_info);
1112 if (wccp2r1_alt_assignment_map)
1113 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_alt_assignment_map);
1114 break;
1116 case WCCP2_REMOVAL_QUERY:
1117 if (!wccp2_security_info)
1118 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_security_info);
1119 if (!wccp2_service_info)
1120 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_service_info);
1121 if (wccp2_router_id_info)
1122 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_router_id_info);
1123 if (wccp2_wc_id_info)
1124 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_wc_id_info);
1125 if (wccp2_rtr_view_info)
1126 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_rtr_view_info);
1127 if (wccp2_wc_view_info)
1128 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_wc_view_info);
1129 if (wccp2_redirect_assignment)
1130 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_redirect_assignment);
1131 if (!wccp2_query_info)
1132 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_query_info);
1133 if (wccp2_capabilities_info)
1134 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_capabilities_info);
1135 if (wccp2_alt_assignment)
1136 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_alt_assignment);
1137 if (wccp2_assign_map)
1138 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_assign_map);
1139 if (wccp2_command_extension)
1140 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_command_extension);
1141 if (wccp2r1_alt_assignment_map)
1142 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_alt_assignment_map);
1143 break;
1145 case WCCP2_REDIRECT_ASSIGN:
1146 if (!wccp2_security_info)
1147 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_security_info);
1148 if (!wccp2_service_info)
1149 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_service_info);
1150 if (wccp2_router_id_info)
1151 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_router_id_info);
1152 if (wccp2_wc_id_info)
1153 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_wc_id_info);
1154 if (wccp2_rtr_view_info)
1155 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_rtr_view_info);
1156 if (wccp2_wc_view_info)
1157 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_wc_view_info);
1158 if (wccp2_query_info)
1159 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_query_info);
1160 if (wccp2_capabilities_info)
1161 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_capabilities_info);
1162 if (! (wccp2_assign_map || wccp2r1_alt_assignment_map || wccp2_alt_assignment || wccp2_redirect_assignment))
1163 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_assignment);
1164 if (wccp2_command_extension)
1165 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_command_extension);
1166 break;
1170 /* the following functions all need to check the length and the offset
1171 so we have a few macros to use
1174 #define EAT(x) {length -= x; offset += x;}
1176 #define EAT_AND_CHECK(x,next) {length -= x; offset += x; if (length < next) return length - next;}
1178 #define NOTE_EATEN_LENGTH(new_length) {if (new_length<0) return new_length; offset += length-new_length; length = new_length; }
1181 /* 5.1.1 Security Info Component */
1183 /* Security options */
1185 #define WCCP2_NO_SECURITY 0
1186 #define WCCP2_MD5_SECURITY 1
1188 #define SECURITY_INFO_LEN 4
1190 const value_string security_option_vals[] = {
1191 { WCCP2_NO_SECURITY, "None" },
1192 { WCCP2_MD5_SECURITY, "MD5" },
1193 { 0, NULL }
1197 static gint
1198 dissect_wccp2_security_info(tvbuff_t *tvb, int offset, gint length,
1199 packet_info *pinfo _U_, proto_tree *info_tree)
1201 guint32 security_option;
1203 if (length < SECURITY_INFO_LEN)
1204 return (length-SECURITY_INFO_LEN);
1206 security_option = tvb_get_ntohl(tvb, offset);
1207 proto_tree_add_item(info_tree, hf_security_info_option, tvb, offset, 4, ENC_BIG_ENDIAN);
1209 if (security_option == WCCP2_MD5_SECURITY) {
1210 offset += 4;
1212 proto_tree_add_item(info_tree, hf_security_info_md5_checksum, tvb, offset, length-4, ENC_NA);
1214 return length-4-16;
1216 return length-4;
1220 /* 5.1.2 Service Info Component */
1222 #define SERVICE_INFO_LEN (4+4+8*2)
1224 #define WCCP2_SERVICE_STANDARD 0
1225 #define WCCP2_SERVICE_DYNAMIC 1
1227 const value_string service_type_vals[] = {
1228 { WCCP2_SERVICE_STANDARD, "Standard predefined service"},
1229 { WCCP2_SERVICE_DYNAMIC, "Dynamic CE defined service" },
1230 { 0, NULL }
1234 * Service flags.
1236 #define WCCP2_SI_SRC_IP_HASH 0x0001
1237 #define WCCP2_SI_DST_IP_HASH 0x0002
1238 #define WCCP2_SI_SRC_PORT_HASH 0x0004
1239 #define WCCP2_SI_DST_PORT_HASH 0x0008
1240 #define WCCP2_SI_PORTS_DEFINED 0x0010
1241 #define WCCP2_SI_PORTS_SOURCE 0x0020
1242 #define WCCP2r1_SI_REDIRECT_ONLY_PROTOCOL_0 0x0040
1243 #define WCCP2_SI_SRC_IP_ALT_HASH 0x0100
1244 #define WCCP2_SI_DST_IP_ALT_HASH 0x0200
1245 #define WCCP2_SI_SRC_PORT_ALT_HASH 0x0400
1246 #define WCCP2_SI_DST_PORT_ALT_HASH 0x0800
1249 static gint
1250 dissect_wccp2_service_info(tvbuff_t *tvb, int offset, gint length,
1251 packet_info *pinfo, proto_tree *info_tree)
1253 guint8 service_type;
1254 guint32 flags;
1255 proto_item *tf;
1256 proto_tree *field_tree, *ports_tree;
1257 int i;
1258 gchar *buf;
1259 int max_offset = offset+length;
1261 if (length != SERVICE_INFO_LEN)
1262 return length - SERVICE_INFO_LEN;
1264 service_type = tvb_get_guint8(tvb, offset);
1265 proto_tree_add_item(info_tree, hf_service_info_type, tvb,
1266 offset, 1, ENC_BIG_ENDIAN);
1268 switch (service_type) {
1270 case WCCP2_SERVICE_STANDARD:
1271 proto_tree_add_item(info_tree, hf_service_info_id_standard, tvb,
1272 offset +1 , 1, ENC_BIG_ENDIAN);
1274 tf = proto_tree_add_item(info_tree, hf_service_info_priority, tvb, offset+2, 1, ENC_BIG_ENDIAN);
1275 if (tvb_get_guint8(tvb, offset+2) != 0)
1276 expert_add_info(pinfo, tf, &ei_wccp_service_info_priority_nonzero);
1278 tf = proto_tree_add_item(info_tree, hf_service_info_protocol, tvb,
1279 offset+3, 1, ENC_BIG_ENDIAN);
1281 if (tvb_get_guint8(tvb, offset+3) != 0)
1282 expert_add_info(pinfo, tf, &ei_wccp_service_info_protocol_nonzero);
1283 break;
1285 case WCCP2_SERVICE_DYNAMIC:
1286 proto_tree_add_item(info_tree, hf_service_info_id_dynamic, tvb,
1287 offset +1 , 1, ENC_BIG_ENDIAN);
1288 proto_tree_add_item(info_tree, hf_service_info_priority, tvb,
1289 offset+2, 1, ENC_BIG_ENDIAN);
1290 proto_tree_add_item(info_tree, hf_service_info_protocol, tvb,
1291 offset+3, 1, ENC_BIG_ENDIAN);
1292 break;
1294 offset += 4;
1296 flags = tvb_get_ntohl(tvb, offset);
1297 tf = proto_tree_add_item(info_tree, hf_service_info_flags, tvb, offset, 4, ENC_BIG_ENDIAN);
1299 field_tree = proto_item_add_subtree(tf, ett_service_flags);
1300 proto_tree_add_item(field_tree, hf_service_info_flags_src_ip_hash, tvb, offset, 4, ENC_BIG_ENDIAN);
1301 proto_tree_add_item(field_tree, hf_service_info_flags_dest_ip_hash, tvb, offset, 4, ENC_BIG_ENDIAN);
1302 proto_tree_add_item(field_tree, hf_service_info_flags_src_port_hash, tvb, offset, 4, ENC_BIG_ENDIAN);
1303 proto_tree_add_item(field_tree, hf_service_info_flags_dest_port_hash, tvb, offset, 4, ENC_BIG_ENDIAN);
1304 proto_tree_add_item(field_tree, hf_service_info_flags_ports_defined, tvb, offset, 4, ENC_BIG_ENDIAN);
1305 /* if they are defined which ? */
1306 if (flags & WCCP2_SI_PORTS_DEFINED)
1307 proto_tree_add_item(field_tree, hf_service_info_flags_ports_source, tvb, offset, 4, ENC_BIG_ENDIAN);
1309 proto_tree_add_item(field_tree, hf_service_info_flags_redirect_only_protocol_0, tvb, offset, 4, ENC_BIG_ENDIAN);
1310 proto_tree_add_item(field_tree, hf_service_info_flags_src_ip_alt_hash, tvb, offset, 4, ENC_BIG_ENDIAN);
1311 proto_tree_add_item(field_tree, hf_service_info_flags_dest_ip_alt_hash, tvb, offset, 4, ENC_BIG_ENDIAN);
1312 proto_tree_add_item(field_tree, hf_service_info_flags_src_port_alt_hash, tvb, offset, 4, ENC_BIG_ENDIAN);
1313 proto_tree_add_item(field_tree, hf_service_info_flags_dest_port_alt_hash, tvb, offset, 4, ENC_BIG_ENDIAN);
1315 buf= (char *) wmem_alloc(wmem_packet_scope(), 128);
1316 decode_bitfield_value(buf, flags,
1317 0xFFFFFFFF ^ (WCCP2_SI_SRC_IP_HASH
1318 | WCCP2_SI_DST_IP_HASH
1319 | WCCP2_SI_SRC_PORT_HASH
1320 | WCCP2_SI_DST_PORT_HASH
1321 | WCCP2_SI_PORTS_DEFINED
1322 | WCCP2_SI_PORTS_SOURCE
1323 | WCCP2r1_SI_REDIRECT_ONLY_PROTOCOL_0
1324 | WCCP2_SI_SRC_IP_ALT_HASH
1325 | WCCP2_SI_DST_IP_ALT_HASH
1326 | WCCP2_SI_SRC_PORT_ALT_HASH
1327 | WCCP2_SI_DST_PORT_ALT_HASH),
1328 32);
1329 proto_tree_add_text(field_tree, tvb, offset, 2,
1330 "%s : %s",
1331 buf, "reserved, should be 0");
1333 offset += 4;
1335 if (flags & WCCP2_SI_PORTS_DEFINED) {
1336 tf = proto_tree_add_text(info_tree, tvb, offset, 2*8,
1337 "Ports list: ");
1338 ports_tree = proto_item_add_subtree(tf, ett_service_info_ports);
1340 for (i = 0; i < 8; i++) {
1341 guint16 port = tvb_get_ntohs(tvb, offset);
1343 if (port) {
1344 if (flags & WCCP2_SI_SRC_PORT_HASH)
1345 proto_tree_add_item(ports_tree, hf_service_info_source_port, tvb, offset, 2, ENC_BIG_ENDIAN);
1346 else
1347 proto_tree_add_item(ports_tree, hf_service_info_destination_port, tvb, offset, 2, ENC_BIG_ENDIAN);
1348 proto_item_append_text(tf, " %d", port);
1350 offset += 2;
1351 DISSECTOR_ASSERT(offset <= max_offset);
1354 else {
1355 /* just use up the space if there is */
1356 if (offset + 8 * 2 <= max_offset) {
1357 proto_tree_add_text(info_tree, tvb, offset, 8*2,
1358 "Ports fields not used");
1359 /*offset += 8*2;*/
1363 return length - SERVICE_INFO_LEN;
1366 /* 6.1 Router Identity Element */
1367 static void
1368 dissect_wccp2_router_identity_element(tvbuff_t *tvb, int offset, packet_info *pinfo,
1369 proto_tree *tree)
1371 proto_item *tf;
1374 proto_tree_add_item(tree, hf_router_identity_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1375 tf = proto_tree_add_item(tree, hf_router_identity_receive_id, tvb, offset+4, 4, ENC_BIG_ENDIAN);
1377 if (tvb_get_ntohl(tvb, offset + 4) == 0)
1378 expert_add_info(pinfo, tf, &ei_wccp_router_identity_receive_id_zero);
1381 #define ROUTER_ID_INFO_MIN_LEN (8+4+4)
1383 /* 5.3.1 Router Identity Info Component */
1384 static gint
1385 dissect_wccp2_router_identity_info(tvbuff_t *tvb, int offset, gint length,
1386 packet_info *pinfo, proto_tree *info_tree)
1388 guint32 n_received_from;
1389 guint i;
1390 proto_item *te;
1391 proto_tree *element_tree;
1393 if (length < 8)
1394 return length - ROUTER_ID_INFO_MIN_LEN;
1397 te = proto_tree_add_item(info_tree, hf_router_identity_router_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1399 element_tree = proto_item_add_subtree(te,ett_wc_view_info_router_element);
1401 dissect_wccp2_router_identity_element(tvb,offset,pinfo,element_tree);
1402 EAT_AND_CHECK(8,4);
1405 proto_tree_add_item(info_tree, hf_router_identity_send_to_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1406 EAT_AND_CHECK(4,4);
1408 n_received_from = tvb_get_ntohl(tvb, offset);
1409 proto_tree_add_item(info_tree, hf_router_identity_received_from_num, tvb, offset, 4, ENC_BIG_ENDIAN);
1410 EAT(4);
1412 for (i = 0; i < n_received_from; i++) {
1413 if (length < 4)
1414 return length-4*(i-n_received_from);
1417 proto_tree_add_item(info_tree, hf_router_identity_received_from_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1418 EAT(4);
1421 return length;
1424 #define ROUTER_WC_ID_ELEMENT_MIN_LEN (4+2+2)
1426 /* 6.4 Web-Cache Identity Element */
1427 static gint
1428 dissect_wccp2_web_cache_identity_element(tvbuff_t *tvb, int offset, gint length, packet_info *pinfo,
1429 proto_tree *info_tree)
1431 proto_item *tf;
1432 proto_tree *field_tree;
1433 guint16 flags;
1434 guint data_element_type;
1435 char *buf;
1437 if (length < ROUTER_WC_ID_ELEMENT_MIN_LEN)
1438 return length - ROUTER_WC_ID_ELEMENT_MIN_LEN;
1440 proto_tree_add_item(info_tree, hf_web_cache_identity_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1441 EAT_AND_CHECK(4,2);
1443 tf = proto_tree_add_item(info_tree, hf_web_cache_identity_hash_rev, tvb, offset, 2, ENC_BIG_ENDIAN);
1444 if (tvb_get_ntohs(tvb, offset) != 0)
1445 expert_add_info(pinfo, tf, &ei_wccp_web_cache_identity_hash_rev_zero);
1447 EAT_AND_CHECK(2,2);
1449 flags = tvb_get_ntohs(tvb, offset);
1450 tf = proto_tree_add_uint(info_tree, hf_web_cache_identity_flags, tvb, offset, 2, flags);
1451 data_element_type = (flags & 0x6) >> 1;
1453 field_tree = proto_item_add_subtree(tf, ett_wc_identity_flags);
1454 proto_tree_add_item(field_tree, hf_web_cache_identity_flag_hash_info, tvb, offset, 2, ENC_BIG_ENDIAN);
1455 proto_tree_add_item(field_tree, hf_web_cache_identity_flag_assign_type, tvb, offset, 2, ENC_BIG_ENDIAN);
1456 proto_tree_add_item(field_tree, hf_web_cache_identity_flag_version_request, tvb, offset, 2, ENC_BIG_ENDIAN);
1457 buf=(char *) wmem_alloc(wmem_packet_scope(), 128);
1458 decode_bitfield_value(buf, flags, 0xFFF0, 16);
1459 proto_tree_add_text(field_tree, tvb, offset, 2,
1460 "%s : %s",
1461 buf, "reserved, should be 0");
1462 EAT(2);
1464 switch (data_element_type) {
1465 case WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_HASH:
1466 return dissect_wccp2_hash_assignment_data_element(tvb,offset,length,pinfo,info_tree);
1467 case WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_MASK:
1468 return dissect_wccp2_mask_assignment_data_element(tvb,offset,length,pinfo,info_tree);
1470 case WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_NOT_PRESENT:
1471 proto_tree_add_text(info_tree, tvb, offset, 2,
1472 "No Assignment Data Present");
1473 return length;
1474 break;
1475 case WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_EXTENDED:
1476 return dissect_wccp2_extended_assignment_data_element(tvb,offset,length,pinfo,info_tree);
1478 return length;
1481 /* 5.2.1 Web-Cache Identity Info Component */
1482 static gint
1483 dissect_wccp2_wc_identity_info(tvbuff_t *tvb, int offset, gint length,
1484 packet_info *pinfo _U_, proto_tree *info_tree)
1486 proto_item *te;
1487 proto_tree *element_tree;
1490 te = proto_tree_add_item(info_tree, hf_wc_identity_ip_address, tvb, offset, 4, ENC_BIG_ENDIAN);
1492 element_tree = proto_item_add_subtree(te, ett_wc_identity_element);
1493 return dissect_wccp2_web_cache_identity_element(tvb, offset,length, pinfo,
1494 element_tree);
1497 /* 6.3 Assignment Key Element */
1498 static gint
1499 dissect_wccp2_assignment_key_element(tvbuff_t *tvb, int offset, gint length, packet_info *pinfo _U_,
1500 proto_tree *info_tree)
1502 if (length < 8)
1503 return length -8;
1506 proto_tree_add_item(info_tree, hf_assignment_key_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1508 EAT_AND_CHECK(4,4);
1509 proto_tree_add_item(info_tree, hf_assignment_key_change_num, tvb, offset, 4, ENC_BIG_ENDIAN);
1510 EAT(4);
1512 return length;
1516 #define ROUTER_VIEW_INFO_MIN_LEN (4+8+4+4)
1518 /* 5.3.2 Router View Info Component */
1519 static gint
1520 dissect_wccp2_router_view_info(tvbuff_t *tvb, int offset, gint length,
1521 packet_info *pinfo, proto_tree *info_tree)
1523 guint32 n_routers;
1524 guint32 n_web_caches;
1525 guint i;
1526 proto_item *te;
1527 proto_tree *element_tree;
1528 gint new_length;
1530 if (length < ROUTER_VIEW_INFO_MIN_LEN)
1531 return length - ROUTER_VIEW_INFO_MIN_LEN;
1533 proto_tree_add_item(info_tree, hf_router_view_member_change_num, tvb, offset, 4, ENC_BIG_ENDIAN);
1534 EAT(4);
1536 new_length=dissect_wccp2_assignment_key_element(tvb, offset, length, pinfo, info_tree);
1537 NOTE_EATEN_LENGTH(new_length);
1539 n_routers = tvb_get_ntohl(tvb, offset);
1540 proto_tree_add_uint(info_tree, hf_router_router_num, tvb, offset, 4, n_routers);
1541 EAT(4);
1543 for (i = 0; i < n_routers; i++) {
1544 if (length < 4)
1545 return length - (n_routers-i)*4 - 4;
1547 proto_tree_add_item(info_tree, hf_router_view_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1548 EAT(4);
1551 if (length < 4)
1552 return length - 4;
1554 n_web_caches = tvb_get_ntohl(tvb, offset);
1555 proto_tree_add_uint(info_tree, hf_wc_view_wc_num, tvb, offset, 4, n_web_caches);
1556 EAT(4);
1558 for (i = 0; i < n_web_caches; i++) {
1559 gint old_length;
1560 old_length = length;
1562 if (length < 4)
1563 return length - 4*(n_web_caches-i);
1565 te = proto_tree_add_item(info_tree, hf_router_query_info_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1567 element_tree = proto_item_add_subtree(te, ett_wc_identity_element);
1568 length = dissect_wccp2_web_cache_identity_element(tvb,
1569 offset, length, pinfo,
1570 element_tree);
1571 if (length < 0)
1572 return length;
1574 offset += old_length - length;
1576 return length;
1579 #define WC_VIEW_INFO_MIN_LEN (4+4+4)
1581 /* 5.2.2 Web Cache View Info Component */
1583 static gint
1584 dissect_wccp2_web_cache_view_info(tvbuff_t *tvb, int offset, gint length,
1585 packet_info *pinfo, proto_tree *info_tree)
1587 guint32 n_routers;
1588 guint32 n_web_caches;
1589 guint i;
1590 proto_item *te;
1591 proto_tree *element_tree;
1594 if (length < WC_VIEW_INFO_MIN_LEN)
1595 return length - WC_VIEW_INFO_MIN_LEN;
1598 proto_tree_add_item(info_tree, hf_wc_view_info_change_num, tvb, offset, 4, ENC_BIG_ENDIAN);
1599 EAT_AND_CHECK(4,4);
1601 n_routers = tvb_get_ntohl(tvb, offset);
1602 proto_tree_add_uint(info_tree, hf_wc_view_router_num, tvb, offset, 4, n_routers);
1603 EAT(4);
1605 for (i = 0; i < n_routers; i++) {
1606 if (length < 8)
1607 return length -8 * (n_routers-i) - 4;
1609 te = proto_tree_add_item(info_tree, hf_wc_view_info_router_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1610 /* also include the receive id in the object */
1611 proto_item_set_len(te, 8);
1613 element_tree = proto_item_add_subtree(te,ett_wc_view_info_router_element);
1614 dissect_wccp2_router_identity_element(tvb, offset, pinfo, element_tree);
1615 EAT(8);
1618 if (length < 4)
1619 return length - 4;
1621 n_web_caches = tvb_get_ntohl(tvb, offset);
1622 proto_tree_add_uint(info_tree, hf_wc_view_wc_num, tvb, offset, 4, n_web_caches);
1623 EAT(4);
1625 for (i = 0; i < n_web_caches; i++) {
1626 if (length < 4)
1627 return length - 4*(n_web_caches-i);
1629 proto_tree_add_item(info_tree, hf_wc_view_info_wc_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1630 EAT(4);
1632 return length;
1635 /* 6.2 Router Assignment Element */
1636 static void
1637 dissect_wccp2_router_assignment_element(tvbuff_t *tvb, int offset,
1638 gint length, packet_info *pinfo, proto_tree *info_tree)
1640 dissect_wccp2_router_identity_element(tvb,offset,pinfo,info_tree);
1641 EAT(8);
1642 proto_tree_add_item(info_tree, hf_router_assignment_element_change_num, tvb, offset, 4, ENC_BIG_ENDIAN);
1643 EAT(4);
1646 static gchar *
1647 assignment_bucket_name(guint8 bucket)
1649 gchar *cur;
1651 if (bucket == 0xff) {
1652 cur= (gchar *) "Unassigned";
1653 } else {
1654 cur=wmem_strdup_printf(wmem_packet_scope(), "%u%s", bucket & 0x7F,
1655 (bucket & 0x80) ? " (Alt)" : "");
1657 return cur;
1660 #define ASSIGNMENT_INFO_MIN_LEN (8+4+4)
1662 /* 5.4.1 Assignment Info Component */
1663 static gint
1664 dissect_wccp2_assignment_info(tvbuff_t *tvb, int offset, gint length,
1665 packet_info *pinfo, proto_tree *info_tree)
1667 guint32 n_routers;
1668 guint i;
1669 proto_item *te;
1670 proto_tree *element_tree;
1671 gint new_length;
1673 if (length < ASSIGNMENT_INFO_MIN_LEN)
1674 return length - ASSIGNMENT_INFO_MIN_LEN;
1677 new_length=dissect_wccp2_assignment_key_element(tvb, offset, length, pinfo, info_tree);
1678 NOTE_EATEN_LENGTH(new_length);
1680 n_routers = tvb_get_ntohl(tvb, offset);
1681 proto_tree_add_uint(info_tree, hf_assignment_info_router_num, tvb, offset, 4, n_routers);
1682 EAT(4);
1684 for (i = 0; i < n_routers; i++) {
1685 if (length < 12)
1686 return length - 12*(n_routers-i)-4-256;
1688 te = proto_tree_add_item(info_tree, hf_assignment_info_router_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1690 element_tree = proto_item_add_subtree(te, ett_router_assignment_element);
1691 dissect_wccp2_router_assignment_element(tvb, offset, length , pinfo,
1692 element_tree);
1693 EAT(12);
1696 new_length = dissect_wccp2_hash_buckets_assignment_element(tvb, offset, length, pinfo, info_tree);
1697 NOTE_EATEN_LENGTH(new_length);
1698 return length;
1702 #define QUERY_INFO_LEN (4+4+4+4)
1704 /* 5.5.1 Router Query Info Component */
1705 static gboolean
1706 dissect_wccp2_router_query_info(tvbuff_t *tvb, int offset, gint length,
1707 packet_info *pinfo, proto_tree *info_tree)
1709 if (length < QUERY_INFO_LEN)
1710 return length - QUERY_INFO_LEN;
1712 dissect_wccp2_router_identity_element(tvb,offset,pinfo,info_tree);
1713 EAT_AND_CHECK(8,4);
1715 proto_tree_add_item(info_tree, hf_router_query_info_send_to_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1716 EAT_AND_CHECK(4,4);
1717 proto_tree_add_item(info_tree, hf_router_query_info_target_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1718 EAT(4);
1720 return length;
1723 /* 6.5 Hash Buckets Assignment Element */
1724 static gint dissect_wccp2_hash_buckets_assignment_element(tvbuff_t *tvb, int offset, gint length,
1725 packet_info *pinfo _U_, proto_tree *info_tree)
1727 guint32 i,n_web_caches;
1728 proto_item *te;
1729 proto_tree *element_tree;
1731 if (length < 4)
1732 return length - 4;
1734 n_web_caches = tvb_get_ntohl(tvb, offset);
1735 te = proto_tree_add_uint(info_tree, hf_hash_buckets_assignment_wc_num, tvb, offset, 4, n_web_caches);
1736 EAT(4);
1738 element_tree = proto_item_add_subtree(te,ett_hash_buckets_assignment_wc_element);
1739 for (i = 0; i < n_web_caches; i++) {
1740 proto_item *l_te;
1742 if (length < 4)
1743 return length - 4*(n_web_caches-i)-256;
1745 l_te = proto_tree_add_item(element_tree, hf_hash_buckets_assignment_wc_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1747 proto_item_append_text(l_te, " id: %d", i);
1748 EAT(4);
1751 te = proto_tree_add_text(info_tree,tvb, offset,256, "Buckets");
1752 element_tree = proto_item_add_subtree(te,ett_hash_buckets_assignment_buckets);
1754 for (i = 0; i < 256; i += 4) {
1755 if (length < 4)
1756 return length - (256-i);
1758 proto_tree_add_text(element_tree, tvb, offset, 4,
1759 "Buckets %3d - %3d: %10s %10s %10s %10s",
1760 i, i + 3,
1761 assignment_bucket_name(tvb_get_guint8(tvb, offset)),
1762 assignment_bucket_name(tvb_get_guint8(tvb, offset+1)),
1763 assignment_bucket_name(tvb_get_guint8(tvb, offset+2)),
1764 assignment_bucket_name(tvb_get_guint8(tvb, offset+3)));
1765 EAT(4);
1767 return length;
1770 #define WCCP2_FORWARDING_METHOD_GRE 0x00000001
1771 #define WCCP2_FORWARDING_METHOD_L2 0x00000002
1773 static const capability_flag forwarding_method_flags[] = {
1774 { WCCP2_FORWARDING_METHOD_GRE, "IP-GRE", &hf_capability_forwarding_method_flag_gre },
1775 { WCCP2_FORWARDING_METHOD_L2, "L2", &hf_capability_forwarding_method_flag_l2 },
1776 { 0, NULL, NULL }
1779 #define WCCP2_ASSIGNMENT_METHOD_HASH 0x00000001
1780 #define WCCP2_ASSIGNMENT_METHOD_MASK 0x00000002
1782 static const capability_flag assignment_method_flags[] = {
1783 { WCCP2_ASSIGNMENT_METHOD_HASH, "Hash", &hf_capability_assignment_method_flag_hash },
1784 { WCCP2_ASSIGNMENT_METHOD_MASK, "Mask", &hf_capability_assignment_method_flag_mask },
1785 { 0, NULL, NULL }
1789 #define WCCP2_PACKET_RETURN_METHOD_GRE 0x00000001
1790 #define WCCP2_PACKET_RETURN_METHOD_L2 0x00000002
1792 static const capability_flag packet_return_method_flags[] = {
1793 { WCCP2_PACKET_RETURN_METHOD_GRE, "IP-GRE", &hf_capability_return_method_flag_gre },
1794 { WCCP2_PACKET_RETURN_METHOD_L2, "L2", &hf_capability_return_method_flag_l2 },
1795 { 0, NULL, NULL }
1798 #define WCCP2_COMMAND_TYPE_SHUTDOWN 1
1799 #define WCCP2_COMMAND_TYPE_SHUTDOWN_RESPONSE 2
1801 static const value_string wccp_command_type_vals[] = {
1802 { WCCP2_COMMAND_TYPE_SHUTDOWN, "CE shutting down" },
1803 { WCCP2_COMMAND_TYPE_SHUTDOWN_RESPONSE, "Router Acknowledge CE shutdown"},
1804 { 0, NULL }
1809 /* 5.1.3 Capabilities Info Component */
1811 static gint
1812 dissect_wccp2_capability_info(tvbuff_t *tvb, int offset, gint length,
1813 packet_info *pinfo, proto_tree *info_tree)
1815 gint capability_length;
1817 while (length >= 8) {
1818 capability_length = dissect_wccp2_capability_element(tvb,offset,length,pinfo,info_tree);
1820 NOTE_EATEN_LENGTH(capability_length);
1822 return length;
1826 #define ALT_COMMAND_EXTENSION_MIN_LEN (4)
1828 /* 5.1.4 && 6.12 Command Extension Component */
1830 static gint
1831 dissect_wccp2_command_extension(tvbuff_t *tvb, int offset,
1832 int length, packet_info *pinfo _U_, proto_tree *info_tree)
1834 guint16 command_type;
1835 guint16 command_length;
1837 for (;;) {
1838 if (length == 0)
1839 return length;
1841 if (length < ALT_COMMAND_EXTENSION_MIN_LEN )
1842 return length - ALT_COMMAND_EXTENSION_MIN_LEN ;
1844 command_type = tvb_get_ntohs(tvb, offset);
1845 proto_tree_add_item(info_tree, hf_command_element_type, tvb, offset, 2, ENC_BIG_ENDIAN);
1846 EAT_AND_CHECK(2,2);
1849 command_length = tvb_get_ntohs(tvb, offset);
1850 proto_tree_add_item(info_tree, hf_command_element_length, tvb, offset, 2, ENC_BIG_ENDIAN);
1851 proto_tree_add_text(info_tree, tvb, offset, 2,
1852 "Command length: %u", command_length);
1853 EAT(2);
1855 if (((command_type == WCCP2_COMMAND_TYPE_SHUTDOWN) ||
1856 (command_type == WCCP2_COMMAND_TYPE_SHUTDOWN_RESPONSE)) &&
1857 (command_length == 4)) {
1858 if (length < 4)
1859 return length - 4;
1860 proto_tree_add_item(info_tree, hf_command_element_shutdown_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1861 } else {
1862 if (length < command_length)
1863 return length - command_length;
1865 proto_tree_add_text(info_tree, tvb, offset, command_length,
1866 "Unknown command");
1868 EAT(command_length);
1873 /* 5.1.5 Address Table Component */
1874 /* this function is special as it can be invoked twice during a packet decode:
1875 once to get the tables, once to display them
1877 static gint
1878 dissect_wccp2r1_address_table_info(tvbuff_t *tvb, int offset,
1879 int length, packet_info *pinfo, proto_tree *info_tree)
1881 guint16 address_length;
1882 guint32 i;
1883 proto_tree *element_tree=NULL;
1884 proto_item *tf=NULL;
1886 wccp_wccp_address_table.in_use = TRUE;
1888 if (info_tree)
1889 tf = proto_tree_get_parent(info_tree);
1891 if (length < 2*4)
1892 return length - 2*4;
1895 wccp_wccp_address_table.family = tvb_get_ntohs(tvb,offset);
1896 if (pinfo && info_tree)
1897 proto_tree_add_item(info_tree, hf_address_table_family, tvb,
1898 offset, 2, ENC_BIG_ENDIAN);
1899 EAT_AND_CHECK(2,2);
1901 address_length = tvb_get_ntohs(tvb,offset);
1902 if (info_tree)
1903 proto_tree_add_item(info_tree, hf_address_table_address_length, tvb, offset, 2, ENC_BIG_ENDIAN);
1904 EAT_AND_CHECK(2,2);
1906 wccp_wccp_address_table.table_length = tvb_get_ntohl(tvb,offset);
1907 if (pinfo && info_tree) {
1908 tf = proto_tree_add_item(info_tree, hf_address_table_length, tvb, offset, 4, ENC_BIG_ENDIAN);
1909 element_tree = proto_item_add_subtree(tf, ett_table_element);
1911 EAT(4);
1913 /* check if the length is valid and allocate the tables if needed*/
1914 switch (wccp_wccp_address_table.family) {
1915 case 1:
1916 if (wccp_wccp_address_table.table_ipv4 == NULL)
1917 wccp_wccp_address_table.table_ipv4 = (guint32 *)
1918 wmem_alloc(wmem_packet_scope(), wccp_wccp_address_table.table_length * 4);
1919 if ((address_length != 4) && (pinfo && info_tree)) {
1920 expert_add_info_format(pinfo, tf, &ei_wccp_length_bad,
1921 "The Address length must be 4, but I found %d for IPv4 addresses. Correcting this.",
1922 address_length);
1923 address_length = 4;
1925 break;
1926 case 2:
1927 if (wccp_wccp_address_table.table_ipv6 == NULL)
1928 wccp_wccp_address_table.table_ipv6 = (struct e_in6_addr *)
1929 wmem_alloc(wmem_packet_scope(), wccp_wccp_address_table.table_length * sizeof(struct e_in6_addr));
1930 if ((address_length != 16) && (pinfo && info_tree)) {
1931 expert_add_info_format(pinfo, tf, &ei_wccp_length_bad,
1932 "The Address length must be 16, but I found %d for IPv6 addresses. Correcting this",
1933 address_length);
1934 address_length=16;
1936 break;
1937 default:
1938 if (pinfo && info_tree) {
1939 expert_add_info_format(pinfo, tf, &ei_wccp_address_table_family_unknown,
1940 "Unknown address family: %d", wccp_wccp_address_table.family);
1944 /* now read the addresses and print/store them */
1946 for(i=0; i<wccp_wccp_address_table.table_length; i++) {
1947 const gchar* addr;
1949 /* do we have space? */
1950 if (length < address_length) {
1951 if (pinfo && tf)
1952 expert_add_info_format(pinfo, tf, &ei_wccp_length_bad, "Ran out of space to decode");
1954 /* first clean up: */
1955 wccp_wccp_address_table.in_use = FALSE;
1956 wccp_wccp_address_table.family = -1;
1957 wccp_wccp_address_table.version = -1;
1958 wccp_wccp_address_table.table_length = 0;
1959 wccp_wccp_address_table.table_ipv4 = (guint32 *) NULL;
1960 wccp_wccp_address_table.table_ipv6 = (struct e_in6_addr *)NULL;
1962 /* ABORT The decode */
1963 return length - address_length;
1966 switch (wccp_wccp_address_table.family) {
1967 case 1:
1968 /* IPv4 */
1969 addr = tvb_ip_to_str(tvb, offset);
1970 if (wccp_wccp_address_table.table_ipv4 != NULL)
1971 wccp_wccp_address_table.table_ipv4[i] = tvb_get_ntohl(tvb,offset);
1972 break;
1973 case 2:
1974 /* IPv6 */
1975 addr = tvb_ip6_to_str(tvb,offset);
1976 if (wccp_wccp_address_table.table_ipv6 != NULL)
1977 tvb_get_ipv6(tvb, offset, &(wccp_wccp_address_table.table_ipv6[i]));
1978 break;
1979 default:
1980 addr = wmem_strdup_printf(wmem_packet_scope(), "unknown family");
1983 if (element_tree) {
1984 proto_tree_add_string_format_value(element_tree, hf_address_table_element, tvb,
1985 offset, address_length, addr,
1986 "%d: %s", i+1, addr);
1988 EAT(address_length);
1990 return length;
1997 #define HASH_ASSIGNMENT_INFO_MIN_LEN (4+256)
1999 /* part of 5.6.11 Alternate Assignment Component */
2000 static gint
2001 dissect_wccp2_hash_assignment_info(tvbuff_t *tvb, int offset, gint length,
2002 packet_info *pinfo, proto_tree *info_tree)
2004 guint32 n_web_caches;
2005 guint i;
2007 if (length < HASH_ASSIGNMENT_INFO_MIN_LEN)
2008 return length - ASSIGNMENT_INFO_MIN_LEN;
2010 n_web_caches = tvb_get_ntohl(tvb, offset);
2011 proto_tree_add_uint(info_tree, hf_wc_view_wc_num, tvb, offset, 4, n_web_caches);
2012 EAT(4);
2014 for (i = 0; i < n_web_caches; i++) {
2015 if (length < 4)
2016 return length - 4*(n_web_caches-i)-256;
2018 proto_tree_add_text(info_tree, tvb, offset, 4,
2019 "Web-Cache %d: IP address %s", i,
2020 decode_wccp_encoded_address(tvb, offset, pinfo, info_tree));
2021 EAT(4);
2024 for (i = 0; i < 256; i += 4) {
2025 if (length < 4)
2026 return length - (256-i);
2028 proto_tree_add_text(info_tree, tvb, offset, 4,
2029 "Buckets %d - %d: %10s %10s %10s %10s",
2030 i, i + 3,
2031 assignment_bucket_name(tvb_get_guint8(tvb, offset)),
2032 assignment_bucket_name(tvb_get_guint8(tvb, offset+1)),
2033 assignment_bucket_name(tvb_get_guint8(tvb, offset+2)),
2034 assignment_bucket_name(tvb_get_guint8(tvb, offset+3)));
2035 EAT(4);
2037 return length;
2040 /* 5.3.3 Assignment Map Component */
2041 static gint dissect_wccp2_assignment_map(tvbuff_t *tvb, int offset,
2042 int length, packet_info *pinfo, proto_tree *info_tree)
2044 gint new_length;
2046 new_length=dissect_wccp2_mask_value_set_list(tvb, offset, length, pinfo, info_tree);
2048 NOTE_EATEN_LENGTH(new_length);
2050 return length;
2055 #define ALT_ASSIGNMENT_MAP_MIN_LEN (4)
2057 /* 5.3.4 Alternate Assignment Map Component */
2058 static gint
2059 dissect_wccp2r1_alt_assignment_map_info(tvbuff_t *tvb, int offset,
2060 int length, packet_info *pinfo, proto_tree *info_tree)
2062 guint16 assignment_type;
2063 guint16 assignment_length;
2064 proto_item *tf=NULL;
2066 if (length < ALT_ASSIGNMENT_MAP_MIN_LEN )
2067 return length - ALT_ASSIGNMENT_MAP_MIN_LEN ;
2070 assignment_type = tvb_get_ntohs(tvb, offset);
2071 proto_tree_add_item(info_tree, hf_alt_assignment_map_assignment_type, tvb, offset, 2, ENC_BIG_ENDIAN);
2072 EAT_AND_CHECK(2,2);
2074 assignment_length = tvb_get_ntohs(tvb, offset);
2075 tf=proto_tree_add_item(info_tree, hf_alt_assignment_map_assignment_length, tvb, offset, 2, ENC_BIG_ENDIAN);
2076 EAT(2);
2078 if (length < assignment_length)
2079 expert_add_info_format(pinfo, tf, &ei_wccp_assignment_length_bad,
2080 "Assignment length is %d but only %d remain in the packet. Ignoring this for now",
2081 assignment_length, length);
2083 if (length > assignment_length) {
2084 expert_add_info_format(pinfo, tf, &ei_wccp_assignment_length_bad,
2085 "Assignment length is %d but %d remain in the packet. Assuming that the assignment length is wrong and setting it to %d.",
2086 assignment_length, length, length);
2087 assignment_length = length;
2090 switch (assignment_type) {
2091 case WCCP2_HASH_ASSIGNMENT_TYPE:
2092 return dissect_wccp2_assignment_info(tvb, offset, assignment_length,
2093 pinfo, info_tree);
2094 case WCCP2_MASK_ASSIGNMENT_TYPE:
2095 return dissect_wccp2_mask_value_set_list(tvb, offset, assignment_length,
2096 pinfo, info_tree);
2097 case WCCP2r1_ALT_MASK_ASSIGNMENT_TYPE:
2098 return dissect_wccp2_alternate_mask_value_set_list(tvb, offset, assignment_length,
2099 pinfo, info_tree);
2100 default:
2101 return length;
2109 /* 6.6 Hash Assignment Data Element */
2110 static gint
2111 dissect_wccp2_hash_assignment_data_element(tvbuff_t *tvb, int offset, gint length,
2112 packet_info *pinfo _U_,
2113 proto_tree *info_tree)
2116 proto_item *bucket_item;
2117 proto_tree *bucket_tree;
2118 int i;
2119 guint8 bucket_info;
2120 int n;
2123 bucket_item = proto_tree_add_text(info_tree, tvb, offset, 8*4,
2124 "Hash Assignment Data");
2125 bucket_tree = proto_item_add_subtree(bucket_item, ett_hash_assignment_buckets);
2127 for (i = 0, n = 0; i < 32; i++) {
2128 if (length == 0) {
2129 return -i-2-2;
2132 bucket_info = tvb_get_guint8(tvb, offset);
2133 n = wccp_bucket_info(bucket_info, bucket_tree, n, tvb, offset);
2134 EAT(1);
2137 if (length < 2){
2138 return -2-2;
2141 return dissect_wccp2_assignment_weight_and_status_element(tvb, offset, length, pinfo, info_tree);
2144 /* 6.7 Mask Assignment Data Element */
2145 static gint
2146 dissect_wccp2_mask_assignment_data_element(tvbuff_t *tvb, int offset, gint length, packet_info *pinfo,
2147 proto_tree *info_tree)
2150 proto_item *mask_item;
2151 proto_tree *mask_tree;
2152 gint new_length,start;
2155 mask_item = proto_tree_add_text(info_tree, tvb, offset, 4,
2156 "Mask Assignment Data");
2157 mask_tree = proto_item_add_subtree(mask_item, ett_mask_assignment_data_element);
2158 start = offset;
2160 new_length=dissect_wccp2_mask_value_set_list(tvb, offset, length, pinfo, mask_tree);
2162 NOTE_EATEN_LENGTH(new_length);
2164 if (length < 2)
2165 return length-4;
2167 new_length = dissect_wccp2_assignment_weight_and_status_element(tvb, offset, length, pinfo, info_tree);
2168 NOTE_EATEN_LENGTH(new_length);
2170 proto_item_set_len(mask_item, offset-start);
2171 return length;
2175 /* 5.7.5 Alternate Mask Assignment Data Element */
2176 static gint
2177 dissect_wccp2_alternate_mask_assignment_data_element(tvbuff_t *tvb, int offset, gint length, packet_info *pinfo,
2178 proto_tree *info_tree)
2180 proto_item *mask_item;
2181 proto_tree *mask_tree;
2183 mask_item = proto_tree_add_text(info_tree, tvb, offset, length,
2184 "Alternate Mask Assignment Data");
2185 mask_tree = proto_item_add_subtree(mask_item, ett_alternate_mask_assignment_data_element);
2187 if (length < 4)
2188 return length-4;
2190 if (length > 4)
2191 for (;length >4;)
2193 gint new_length;
2195 new_length=dissect_wccp2_alternate_mask_value_set_list(tvb, offset, length, pinfo, mask_tree);
2197 NOTE_EATEN_LENGTH(new_length);
2200 if (length < 2)
2201 return -2;
2203 return dissect_wccp2_assignment_weight_and_status_element(tvb, offset, length, pinfo, info_tree);
2207 /* 6.9 Assignment Weight and Status Data Element */
2208 static gint
2209 dissect_wccp2_assignment_weight_and_status_element(tvbuff_t *tvb, int offset, gint length,
2210 packet_info *pinfo _U_,
2211 proto_tree *info_tree)
2214 if (length < 4)
2215 return length - 4;
2218 proto_tree_add_item(info_tree, hf_assignment_weight, tvb, offset, 2, ENC_BIG_ENDIAN);
2219 EAT_AND_CHECK(2,2);
2220 proto_tree_add_item(info_tree, hf_assignment_status, tvb, offset, 2, ENC_BIG_ENDIAN);
2221 EAT(2);
2222 return length;
2226 /* 6.10 Extended Assignment Data Element */
2227 static gint
2228 dissect_wccp2_extended_assignment_data_element(tvbuff_t *tvb, int offset, gint length, packet_info *pinfo,
2229 proto_tree *info_tree)
2231 proto_item *element_item, *header;
2232 proto_tree *item_tree;
2234 guint type_of_assignment;
2236 gint assignment_length;
2238 if (length < 4)
2239 return length-4;
2242 header = proto_tree_add_text(info_tree, tvb, offset, length,
2243 "Extended Assignment Data Element");
2245 item_tree = proto_item_add_subtree(header, ett_extended_assigment_data_element);
2247 type_of_assignment = tvb_get_ntohs(tvb, offset);
2248 proto_tree_add_item(item_tree, hf_extended_assignment_data_type, tvb, offset, 2, ENC_BIG_ENDIAN);
2249 EAT_AND_CHECK(2,2);
2251 assignment_length = tvb_get_ntohs(tvb,offset);
2252 element_item = proto_tree_add_item(item_tree, hf_extended_assignment_data_length, tvb, offset, 2, ENC_BIG_ENDIAN);
2253 EAT(2);
2255 if (length < assignment_length)
2256 expert_add_info_format(pinfo, element_item, &ei_wccp_assignment_length_bad,
2257 "Assignment length is %d but only %d remain in the packet. Ignoring this for now",
2258 assignment_length, length);
2260 /* Now a common bug seems to be to set the assignment_length to the length -4
2261 check for this */
2262 if ((length > assignment_length) &&
2263 (length == (assignment_length + 4)))
2265 expert_add_info_format(pinfo, element_item, &ei_wccp_assignment_length_bad,
2266 "Assignment length is %d but %d remain in the packet. Assuming that this is wrong as this is only 4 bytes to small, proceding with the assumption it is %d",
2267 assignment_length, length, length);
2268 assignment_length = length;
2272 proto_item_set_len(header, assignment_length+4);
2274 switch (type_of_assignment)
2276 case WCCP2_HASH_ASSIGNMENT_TYPE:
2277 return dissect_wccp2_hash_assignment_data_element(tvb, offset, assignment_length,
2278 pinfo, item_tree);
2279 case WCCP2_MASK_ASSIGNMENT_TYPE:
2280 return dissect_wccp2_mask_assignment_data_element(tvb, offset, assignment_length,
2281 pinfo, item_tree);
2282 case WCCP2r1_ALT_MASK_ASSIGNMENT_TYPE:
2283 return dissect_wccp2_alternate_mask_assignment_data_element(tvb, offset, assignment_length,
2284 pinfo, item_tree);
2285 case WCCP2r1_ASSIGNMENT_WEIGHT_STATUS:
2286 return dissect_wccp2_assignment_weight_and_status_element(tvb, offset, assignment_length,
2287 pinfo, item_tree);
2289 return length;
2297 /* 6.11 Capability Element */
2298 static gint
2299 dissect_wccp2_capability_element(tvbuff_t *tvb, int offset, gint length,
2300 packet_info *pinfo, proto_tree *info_tree)
2302 guint16 capability_type;
2303 guint16 capability_val_len;
2304 proto_item *te, *header, *tf;
2305 proto_tree *element_tree;
2307 if (length < 4)
2308 return length - 4;
2311 capability_type = tvb_get_ntohs(tvb, offset);
2312 capability_val_len = tvb_get_ntohs(tvb, offset + 2);
2313 header = te = proto_tree_add_item(info_tree, hf_capability_element_type, tvb, offset, 2, ENC_BIG_ENDIAN);
2315 proto_item_set_len(te, capability_val_len + 4);
2316 element_tree = proto_item_add_subtree(te, ett_capability_element);
2318 tf = proto_tree_add_uint(element_tree, hf_capability_element_length, tvb, offset+2, 2, capability_val_len);
2320 proto_tree_add_text(element_tree, tvb, offset, 2,
2321 "Type: %s",
2322 val_to_str(capability_type,
2323 capability_type_vals, "Unknown (0x%08X)"));
2324 if (capability_val_len < 4) {
2325 expert_add_info_format(pinfo, tf, &ei_wccp_capability_element_length,
2326 "Value Length: %u (illegal, must be >= 4)", capability_val_len);
2327 return -length;
2330 if (length < (4+capability_val_len))
2331 return length - 4 - capability_val_len;
2333 switch (capability_type) {
2334 case WCCP2_FORWARDING_METHOD:
2335 dissect_32_bit_capability_flags(tvb, offset,
2336 capability_val_len,
2337 ett_capability_forwarding_method,
2338 forwarding_method_flags, element_tree, header);
2339 break;
2341 case WCCP2_ASSIGNMENT_METHOD:
2342 dissect_32_bit_capability_flags(tvb, offset,
2343 capability_val_len,
2344 ett_capability_assignment_method,
2345 assignment_method_flags, element_tree, header);
2346 break;
2348 case WCCP2_PACKET_RETURN_METHOD:
2349 dissect_32_bit_capability_flags(tvb, offset,
2350 capability_val_len,
2351 ett_capability_return_method,
2352 packet_return_method_flags, element_tree, header);
2353 break;
2355 case WCCP2_TRANSMIT_T:
2356 dissect_transmit_t_capability(tvb, te, offset,
2357 capability_val_len,
2358 ett_capability_transmit_t,element_tree);
2359 break;
2361 case WCCP2_TIMER_SCALE:
2362 dissect_timer_scale_capability(tvb, offset,
2363 capability_val_len,
2364 ett_capability_timer_scale, element_tree);
2365 break;
2366 default:
2367 proto_tree_add_text(element_tree, tvb,
2368 offset, capability_val_len,
2369 "Value: %s",
2370 tvb_bytes_to_str(tvb, offset,
2371 capability_val_len));
2372 break;
2374 return length - 4 - capability_val_len;
2378 /* 6.13 Mask/Value Set List */
2379 static gint
2380 dissect_wccp2_mask_value_set_list(tvbuff_t *tvb, int offset,
2381 int length, packet_info *pinfo, proto_tree *info_tree)
2383 guint num_of_elem;
2384 guint i;
2385 proto_item *te;
2386 proto_tree *element_tree;
2387 guint start;
2390 if (length < 4)
2391 return length - 4;
2393 te = proto_tree_add_text(info_tree, tvb, offset, 4, "Mask/Value Set List");
2394 element_tree = proto_item_add_subtree(te, ett_mv_set_list);
2395 start = offset;
2398 num_of_elem = tvb_get_ntohl(tvb, offset);
2399 proto_tree_add_item(element_tree, hf_mask_value_set_list_num_elements,
2400 tvb, offset, 4, ENC_BIG_ENDIAN);
2401 /* proto_tree_add_uint(element_tree, , tvb, offset, 4, num_of_elem); */
2402 EAT(4);
2404 for (i = 0; i < num_of_elem; i++)
2406 gint new_length;
2408 new_length=dissect_wccp2_mask_value_set_element(tvb, offset, length, i, pinfo, element_tree);
2410 NOTE_EATEN_LENGTH(new_length);
2413 proto_item_set_len(te, offset-start);
2414 return length;
2421 /* 6.15 Mask Element */
2422 static gint
2423 dissect_wccp2_mask_element(tvbuff_t *tvb, int offset, gint length, packet_info *pinfo _U_, proto_tree *info_tree)
2425 if (length < 2)
2426 return length-12;
2428 proto_tree_add_item(info_tree, hf_mask_element_src_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
2429 EAT_AND_CHECK(4,4);
2430 proto_tree_add_item(info_tree, hf_mask_element_dest_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
2432 EAT_AND_CHECK(4,2);
2433 proto_tree_add_item(info_tree, hf_mask_element_src_port, tvb, offset, 2, ENC_BIG_ENDIAN);
2434 EAT_AND_CHECK(2,2);
2435 proto_tree_add_item(info_tree, hf_mask_element_dest_port, tvb, offset, 2, ENC_BIG_ENDIAN);
2436 EAT(2);
2438 return length;
2446 /* 6.17 Alternate Mask/Value Set List */
2447 static gint dissect_wccp2_alternate_mask_value_set_list(tvbuff_t *tvb, int offset,
2448 int length, packet_info *pinfo, proto_tree *info_tree)
2450 proto_item *header;
2451 proto_tree *list_tree;
2452 guint num_of_val_elements;
2453 guint i;
2455 if (length < 4)
2456 return length - 4;
2458 header = proto_tree_add_text(info_tree, tvb, offset, length,
2459 "Alternate Mask/Value Set List");
2460 list_tree = proto_item_add_subtree(header, ett_alternate_mask_value_set);
2462 num_of_val_elements = tvb_get_ntohl(tvb, offset);
2463 proto_tree_add_uint(list_tree, hf_alt_assignment_mask_value_set_list_num_elements, tvb, offset, 4, num_of_val_elements);
2464 EAT(4);
2466 for(i=0;i<num_of_val_elements;i++) {
2467 gint new_length;
2469 new_length=dissect_wccp2_alternate_mask_value_set_element(tvb, offset, length, i, pinfo, list_tree);
2471 NOTE_EATEN_LENGTH(new_length);
2473 return length;
2477 /* 6.18 Alternate Mask/Value Set Element */
2478 static gint
2479 dissect_wccp2_alternate_mask_value_set_element(tvbuff_t *tvb, int offset, gint length, guint el_index, packet_info *pinfo, proto_tree *info_tree)
2481 proto_item *tl, *header;
2482 proto_tree *element_tree, *value_tree;
2483 guint number_of_elements;
2484 gint new_length, total_length;
2485 guint i;
2487 header = proto_tree_add_text(info_tree, tvb, offset, 0,
2488 "Alternate Mask/Value Set Element(%d)", el_index);
2489 element_tree = proto_item_add_subtree(header, ett_alternate_mask_value_set_element);
2491 total_length = 0;
2493 new_length=dissect_wccp2_mask_element(tvb,offset,length,pinfo,element_tree);
2494 total_length += length - new_length;
2495 NOTE_EATEN_LENGTH(new_length);
2497 if (length < 4)
2498 return length - 4;
2500 number_of_elements = tvb_get_ntohl(tvb, offset);
2501 tl = proto_tree_add_uint(element_tree, hf_alt_assignment_mask_value_set_element_num_wc_value_elements, tvb, offset, 4, number_of_elements);
2502 value_tree = proto_item_add_subtree(tl, ett_alternate_mv_set_element_list);
2503 total_length += 4;
2504 EAT(4);
2506 for (i=0; i < number_of_elements; i++) {
2507 new_length=dissect_wccp2_web_cache_value_element(tvb, offset, length, pinfo, value_tree);
2508 total_length += length - new_length;
2509 NOTE_EATEN_LENGTH(new_length);
2511 proto_item_set_len(header, total_length);
2513 return length;
2516 /* 6.19 Web-Cache Value Element */
2517 static gint
2518 dissect_wccp2_web_cache_value_element(tvbuff_t *tvb, int offset, gint length, packet_info *pinfo _U_, proto_tree *info_tree)
2520 guint number_of_elements;
2521 proto_item *tl;
2522 proto_tree *element_tree;
2523 guint i;
2525 if (length < 4)
2526 return length - 8;
2528 tl = proto_tree_add_item(info_tree, hf_web_cache_value_element_wc_address, tvb, offset, 4, ENC_BIG_ENDIAN);
2530 element_tree = proto_item_add_subtree(tl, ett_web_cache_value_element_list);
2531 EAT_AND_CHECK(4,4);
2533 number_of_elements = tvb_get_ntohl(tvb, offset);
2534 proto_tree_add_uint(element_tree, hf_web_cache_value_element_num_values, tvb, offset, 4, number_of_elements);
2535 EAT(4);
2537 for (i=0; i < number_of_elements; i++) {
2538 if (length < 4)
2539 return length - 4*(number_of_elements-i);
2541 proto_tree_add_text(element_tree, tvb, offset, 4,
2542 "Value Sequence Number %d: %x",
2543 i+1,
2544 tvb_get_ntohl(tvb, offset));
2545 EAT(4);
2548 return length;
2552 /* End of standard functions */
2555 static void
2556 dissect_32_bit_capability_flags(tvbuff_t *tvb, int curr_offset,
2557 guint16 capability_val_len, gint ett, const capability_flag *flags,
2558 proto_tree *element_tree, proto_item *header)
2560 guint32 capability_val;
2561 proto_item *tm;
2562 proto_tree *method_tree;
2563 int i;
2564 gboolean first = TRUE;
2566 capability_val = tvb_get_ntohl(tvb, curr_offset + 4);
2567 tm = proto_tree_add_uint(element_tree, hf_capability_info_value, tvb, curr_offset + 4, 4, capability_val);
2569 DISSECTOR_ASSERT(capability_val_len == 4);
2571 for (i = 0; flags[i].short_name != NULL; i++) {
2572 if (capability_val & flags[i].value) {
2573 if (first) {
2574 proto_item_append_text( tm, " (%s", flags[i].short_name);
2575 proto_item_append_text( header, " (%s", flags[i].short_name);
2576 first = FALSE;
2577 } else {
2578 proto_item_append_text( tm, ", %s", flags[i].short_name);
2579 proto_item_append_text( header, " (%s", flags[i].short_name);
2584 if (first == FALSE) {
2585 proto_item_append_text( tm, ")");
2586 proto_item_append_text( header, ")");
2589 method_tree = proto_item_add_subtree(tm, ett);
2590 for (i = 0; flags[i].phf != NULL; i++)
2591 proto_tree_add_item(method_tree, *(flags[i].phf), tvb, curr_offset+4, 4, ENC_BIG_ENDIAN);
2596 /* 6.11.4 Capability Type WCCP2_TRANSMIT_T */
2597 static void
2598 dissect_transmit_t_capability(tvbuff_t *tvb, proto_item *te, int curr_offset,
2599 guint16 capability_val_len, gint ett, proto_tree *element_tree)
2601 guint16 upper_limit, lower_limit;
2602 proto_item *tm;
2603 proto_tree *method_tree;
2605 DISSECTOR_ASSERT(capability_val_len == 4);
2607 upper_limit = tvb_get_ntohs(tvb, curr_offset);
2608 lower_limit = tvb_get_ntohs(tvb, curr_offset + 2);
2610 if ( upper_limit == 0) {
2611 tm = proto_tree_add_text(element_tree, tvb, curr_offset, 2,
2612 "Only accepting one value");
2613 method_tree = proto_item_add_subtree(tm, ett);
2614 proto_tree_add_text(method_tree, tvb, curr_offset, 2,
2615 "Reserved, must be 0: %d", upper_limit);
2617 proto_tree_add_item(method_tree, hf_capability_transmit_t , tvb, curr_offset+2, 2, ENC_BIG_ENDIAN);
2618 proto_item_append_text(te, " %d ms", lower_limit);
2619 } else {
2620 tm = proto_tree_add_text(element_tree, tvb, curr_offset, 2,
2621 "Accepting a range");
2622 method_tree = proto_item_add_subtree(tm, ett);
2623 proto_tree_add_item(method_tree, hf_capability_transmit_t_upper_limit,
2624 tvb, curr_offset, 2, ENC_BIG_ENDIAN);
2626 proto_tree_add_item(method_tree, hf_capability_transmit_t_lower_limit,
2627 tvb, curr_offset+2, 2, ENC_BIG_ENDIAN);
2628 proto_item_append_text(te, " < %d ms > %d ms", lower_limit, upper_limit);
2633 static void
2634 dissect_timer_scale_capability(tvbuff_t *tvb, int curr_offset,
2635 guint16 capability_val_len, gint ett, proto_tree *element_tree)
2637 guint8 a,c;
2638 proto_item *tm;
2639 proto_tree *method_tree;
2641 DISSECTOR_ASSERT(capability_val_len == 4);
2643 a = tvb_get_guint8(tvb, curr_offset);
2644 c = tvb_get_guint8(tvb, curr_offset+2);
2646 if ( a == 0) {
2647 if ( c == 0) {
2648 tm = proto_tree_add_text(element_tree, tvb, curr_offset, 2,
2649 "Only accepting one value");
2651 method_tree = proto_item_add_subtree(tm, ett);
2652 proto_tree_add_text(method_tree, tvb, curr_offset, 1,
2653 "Reserved, must be 0: %d", a);
2655 proto_tree_add_item(method_tree, hf_capability_timer_scale_timeout_scale,
2656 tvb, curr_offset+1, 1, ENC_BIG_ENDIAN);
2657 proto_tree_add_text(method_tree, tvb, curr_offset+2, 1,
2658 "Reserved, must be 0: %d", c);
2659 proto_tree_add_item(method_tree, hf_capability_timer_scale_ra_timer_scale,
2660 tvb, curr_offset+3, 1, ENC_BIG_ENDIAN);
2661 } else {
2662 proto_tree_add_text(element_tree, tvb, curr_offset, 1,
2663 "Error A is 0, but C is not");
2665 } else {
2666 if ( c == 0) {
2667 proto_tree_add_text(element_tree, tvb, curr_offset, 1,
2668 "Error C is 0, but A is not");
2669 } else {
2670 tm = proto_tree_add_text(element_tree, tvb, curr_offset, 2,
2671 "Accepting a range");
2672 method_tree = proto_item_add_subtree(tm, ett);
2673 proto_tree_add_item(method_tree, hf_capability_timer_scale_timeout_scale_upper_limit,
2674 tvb, curr_offset, 1, ENC_BIG_ENDIAN);
2676 proto_tree_add_item(method_tree, hf_capability_timer_scale_timeout_scale_lower_limit,
2677 tvb, curr_offset+1, 1, ENC_BIG_ENDIAN);
2678 proto_tree_add_item(method_tree, hf_capability_timer_scale_ra_scale_upper_limit,
2679 tvb, curr_offset+2, 1, ENC_BIG_ENDIAN);
2680 proto_tree_add_item(method_tree, hf_capability_timer_scale_ra_scale_lower_limit,
2681 tvb, curr_offset+3, 1, ENC_BIG_ENDIAN);
2687 /* 6.16 Value Element */
2688 static gint
2689 dissect_wccp2_value_element(tvbuff_t *tvb, int offset, gint length, int idx, packet_info *pinfo, proto_tree *info_tree)
2691 proto_item *tl;
2692 proto_tree *element_tree;
2694 if (length < 4)
2695 return length - 16;
2697 tl = proto_tree_add_text(info_tree, tvb, offset, 16, "Value Element(%u) %s",
2698 idx,decode_wccp_encoded_address(tvb, offset+4+4+2+2, pinfo, info_tree));
2699 element_tree = proto_item_add_subtree(tl, ett_value_element);
2701 proto_tree_add_item(element_tree, hf_value_element_src_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
2702 EAT_AND_CHECK(4,4);
2703 proto_tree_add_item(element_tree, hf_value_element_dest_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
2705 EAT_AND_CHECK(4,2);
2706 proto_tree_add_item(element_tree, hf_value_element_src_port, tvb, offset, 2, ENC_BIG_ENDIAN);
2707 EAT_AND_CHECK(2,2);
2708 proto_tree_add_item(element_tree, hf_value_element_dest_port, tvb, offset, 2, ENC_BIG_ENDIAN);
2709 EAT_AND_CHECK(2,4);
2711 proto_tree_add_item(element_tree, hf_value_element_web_cache_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
2712 EAT(4);
2714 return length;
2718 /* 6.14 Mask/Value Set Element */
2719 static gint
2720 dissect_wccp2_mask_value_set_element(tvbuff_t *tvb, int offset, gint length, int idx, packet_info *pinfo, proto_tree *info_tree)
2722 proto_item *tl, *te;
2723 proto_tree *element_tree, *value_tree;
2724 guint num_of_val_elements;
2725 guint i;
2726 gint new_length;
2728 tl = proto_tree_add_text(info_tree, tvb, offset, 0,
2729 "Mask/Value Set Element(%d)", idx);
2730 element_tree = proto_item_add_subtree(tl, ett_mv_set_element);
2732 new_length = dissect_wccp2_mask_element(tvb,offset,length,pinfo,element_tree);
2733 NOTE_EATEN_LENGTH(new_length);
2735 if (length < 4)
2736 return length-4;
2738 num_of_val_elements = tvb_get_ntohl(tvb, offset);
2739 te = proto_tree_add_uint(element_tree, hf_mask_value_set_element_value_element_num, tvb, offset, 4, num_of_val_elements);
2741 value_tree = proto_item_add_subtree(te, ett_mv_set_value_list);
2742 EAT(4);
2744 for (i = 0; i < num_of_val_elements; i++)
2746 new_length=dissect_wccp2_value_element(tvb, offset, length, i, pinfo, value_tree);
2748 NOTE_EATEN_LENGTH(new_length);
2751 proto_item_set_len(tl, 16+num_of_val_elements*16);
2753 return length;
2756 #define ALT_ASSIGNMENT_INFO_MIN_LEN (4+4)
2758 /* 5.4.2 Alternate Assignment Component */
2759 static gint
2760 dissect_wccp2_alternate_assignment_info(tvbuff_t *tvb, int offset, gint length,
2761 packet_info *pinfo, proto_tree *info_tree)
2763 guint16 assignment_type;
2764 guint16 assignment_length;
2765 proto_item *tf=NULL;
2767 guint32 n_routers;
2768 guint i;
2769 proto_item *te;
2770 proto_tree *element_tree;
2771 gint new_length;
2774 if (length < ALT_ASSIGNMENT_INFO_MIN_LEN)
2775 return length - ALT_ASSIGNMENT_INFO_MIN_LEN;
2778 assignment_type = tvb_get_ntohs(tvb, offset);
2779 proto_tree_add_item(info_tree, hf_alt_assignment_info_assignment_type, tvb, offset, 2, ENC_BIG_ENDIAN);
2780 EAT_AND_CHECK(2,2);
2782 assignment_length = tvb_get_ntohs(tvb, offset);
2783 tf=proto_tree_add_item(info_tree, hf_alt_assignment_info_assignment_length, tvb, offset, 2, ENC_BIG_ENDIAN);
2784 EAT(2);
2786 if (length < assignment_length)
2787 expert_add_info_format(pinfo, tf, &ei_wccp_assignment_length_bad,
2788 "Assignment length is %d but only %d remain in the packet. Ignoring this for now",
2789 assignment_length, length);
2791 if (length > assignment_length) {
2792 expert_add_info_format(pinfo, tf, &ei_wccp_assignment_length_bad,
2793 "Assignment length is %d but %d remain in the packet. Assuming that the assignment length is wrong and setting it to %d.",
2794 assignment_length, length, length);
2797 new_length=dissect_wccp2_assignment_key_element(tvb, offset, length, pinfo, info_tree);
2798 NOTE_EATEN_LENGTH(new_length);
2800 n_routers = tvb_get_ntohl(tvb, offset);
2801 proto_tree_add_uint(info_tree, hf_alt_assignment_info_num_routers, tvb, offset, 4, n_routers);
2802 EAT(4);
2804 for (i = 0; i < n_routers; i++) {
2805 if (length < 12)
2806 return length - 12*(n_routers-i);
2808 te = proto_tree_add_text(info_tree, tvb, offset, 12,
2809 "Router %d Assignment Element: IP address %s", i,
2810 decode_wccp_encoded_address(tvb, offset, pinfo, info_tree));
2812 element_tree = proto_item_add_subtree(te, ett_router_alt_assignment_element);
2813 dissect_wccp2_router_assignment_element(tvb, offset, length , pinfo, element_tree);
2814 EAT(12);
2817 switch (assignment_type) {
2818 case WCCP2_HASH_ASSIGNMENT_TYPE:
2819 return dissect_wccp2_hash_assignment_info(tvb, offset, length,
2820 pinfo, info_tree);
2821 case WCCP2_MASK_ASSIGNMENT_TYPE:
2822 return dissect_wccp2_mask_value_set_list(tvb, offset, length,
2823 pinfo, info_tree);
2824 case WCCP2r1_ALT_MASK_ASSIGNMENT_TYPE:
2825 return dissect_wccp2_alternate_mask_value_set_list(tvb, offset, length,
2826 pinfo, info_tree);
2827 default:
2828 return length;
2835 /* End of utility functions */
2837 void
2838 proto_register_wccp(void)
2840 static hf_register_info hf[] = {
2841 { &hf_wccp_message_type,
2842 { "WCCP Message Type", "wccp.message", FT_UINT32, BASE_DEC, VALS(wccp_type_vals), 0x0,
2843 "The WCCP message that was sent", HFILL }
2845 { &hf_wccp_version,
2846 { "WCCP Version", "wccp.version", FT_UINT32, BASE_HEX, VALS(wccp_version_val), 0x0,
2847 "The WCCP version", HFILL }
2849 { &hf_message_header_version,
2850 { "WCCP Version (>=2)", "wccp.message_header_version", FT_UINT16, BASE_HEX, NULL, 0x0,
2851 "The WCCP version for version 2 and above", HFILL }
2853 { &hf_hash_revision,
2854 { "Hash Revision", "wccp.hash_revision", FT_UINT32, BASE_DEC, 0x0, 0x0,
2855 "The cache hash revision", HFILL }
2857 { &hf_change_num,
2858 { "Change Number", "wccp.change_num", FT_UINT32, BASE_DEC, 0x0, 0x0,
2859 "The Web-Cache list entry change number", HFILL }
2861 { &hf_hash_flag,
2862 { "Flags", "wccp.hash_flag", FT_UINT32, BASE_HEX, 0x0, 0x0,
2863 NULL, HFILL }
2865 { &hf_hash_flag_u,
2866 { "Hash information", "wccp.hash_flag.u", FT_BOOLEAN, 32, TFS(&tfs_historical_current), 0x10000,
2867 NULL, HFILL }
2869 { &hf_recvd_id,
2870 { "Received ID", "wccp.recvd_id", FT_UINT32, BASE_DEC, 0x0, 0x0,
2871 "The number of I_SEE_YOU's that have been sent", HFILL }
2873 { &hf_cache_ip,
2874 { "Web Cache IP address", "wccp.cache_ip", FT_IPv4, BASE_NONE, NULL, 0x0,
2875 "The IP address of a Web cache", HFILL }
2877 { &hf_wc_num,
2878 { "Number of Web Caches", "wccp.wc_num", FT_UINT32, BASE_DEC, 0x0, 0x0,
2879 NULL, HFILL }
2881 { &hf_message_header_length,
2882 { "Length", "wccp.message_header_length", FT_UINT16, BASE_DEC, 0x0, 0x0,
2883 NULL, HFILL }
2885 { &hf_item_length,
2886 { "Length", "wccp.item_length", FT_UINT16, BASE_DEC, 0x0, 0x0,
2887 "The Length ofthe WCCPv2 item", HFILL }
2889 { &hf_item_type,
2890 { "Type", "wccp.item_type", FT_UINT16, BASE_DEC, VALS(info_type_vals), 0x0,
2891 "The type of the WCCPv2 item", HFILL }
2893 { &hf_item_data,
2894 { "Data", "wccp.item_data", FT_BYTES, BASE_NONE, 0x0, 0x0,
2895 "The data for an unknown item type", HFILL }
2897 { &hf_security_info_option,
2898 { "Security Option", "wccp.security_info_option", FT_UINT16, BASE_DEC, VALS(security_option_vals), 0x0,
2899 NULL, HFILL }
2901 { &hf_security_info_md5_checksum,
2902 { "MD5 checksum (not checked)", "wccp.security_md5_checksum", FT_BYTES, BASE_NONE, 0x0, 0x0,
2903 NULL, HFILL }
2905 { &hf_command_element_type,
2906 {"Command Extension Type", "wccp.command_element_type", FT_UINT16, BASE_DEC, VALS(wccp_command_type_vals), 0x0,
2907 NULL, HFILL }
2909 { &hf_command_element_length,
2910 {"Command Extension Length", "wccp.command_element_length", FT_UINT16, BASE_DEC, NULL, 0x0,
2911 NULL, HFILL }
2913 { &hf_command_element_shutdown_ip,
2914 {"Command Extension Length", "wccp.command_element_shudown_ip", FT_UINT32, BASE_CUSTOM, wccp_fmt_ipadddress, 0x0,
2915 NULL, HFILL }
2917 { &hf_service_info_type,
2918 { "Service Type", "wccp.service_info_type", FT_UINT8, BASE_DEC, VALS(service_type_vals), 0x0,
2919 NULL, HFILL }
2921 { &hf_service_info_id_standard,
2922 { "WCCP Service ID (Standard)", "wccp.service_info_std_id", FT_UINT8, BASE_DEC, VALS(service_id_vals) , 0x0,
2923 "The WCCP Service id (Standard)", HFILL }
2925 { &hf_service_info_id_dynamic,
2926 { "WCCP Service ID ( Dynamic)", "wccp.service_info_dyn_id", FT_UINT8, BASE_DEC, NULL , 0x0,
2927 "The WCCP Service id (Dynamic)", HFILL }
2929 { &hf_service_info_priority,
2930 { "Priority (highest is 255)", "wccp.service_info_priority", FT_UINT8, BASE_DEC, NULL, 0x0,
2931 NULL, HFILL }
2933 { &hf_service_info_protocol,
2934 { "Protocol", "wccp.service_info_protocol", FT_UINT8, BASE_DEC | BASE_EXT_STRING, &ipproto_val_ext, 0x0,
2935 NULL, HFILL }
2937 { &hf_service_info_flags,
2938 { "Flags", "wccp.service_info_flags", FT_UINT32, BASE_HEX, 0x0, 0x0,
2939 NULL, HFILL }
2941 { &hf_service_info_flags_src_ip_hash,
2942 { "Source IP address in primary hash", "wccp.service_info_flag.src_ip_hash", FT_BOOLEAN, 32, TFS(&tfs_used_notused), WCCP2_SI_SRC_IP_HASH,
2943 NULL, HFILL }
2945 { &hf_service_info_flags_dest_ip_hash,
2946 { "Destination IP address in primary hash", "wccp.service_info_flag.dest_ip_hash", FT_BOOLEAN, 32, TFS(&tfs_used_notused), WCCP2_SI_DST_IP_HASH,
2947 NULL, HFILL }
2949 { &hf_service_info_flags_src_port_hash,
2950 { "Source port in primary hash", "wccp.service_info_flag.src_port_hash", FT_BOOLEAN, 32, TFS(&tfs_used_notused), WCCP2_SI_SRC_PORT_HASH,
2951 NULL, HFILL }
2953 { &hf_service_info_flags_dest_port_hash,
2954 { "Destination port in primary hash", "wccp.service_info_flag.dest_port_hash", FT_BOOLEAN, 32, TFS(&tfs_used_notused), WCCP2_SI_DST_PORT_HASH,
2955 NULL, HFILL }
2957 { &hf_service_info_flags_ports_defined,
2958 { "Ports", "wccp.service_info_flag.ports_defined", FT_BOOLEAN, 32, TFS(&tfs_defined_not_defined), WCCP2_SI_PORTS_DEFINED,
2959 NULL, HFILL }
2961 { &hf_service_info_flags_ports_source,
2962 { "Ports refer to", "wccp.service_info_flag.ports_source", FT_BOOLEAN, 32, TFS(&tfs_src_dest_port), WCCP2_SI_PORTS_SOURCE,
2963 NULL, HFILL }
2965 { &hf_service_info_flags_redirect_only_protocol_0,
2966 { "Redirect only protocol 0", "wccp.service_info_flag.redirect_only_protocol_0", FT_BOOLEAN, 32, TFS(&tfs_redirect_protocol0), WCCP2r1_SI_REDIRECT_ONLY_PROTOCOL_0,
2967 NULL, HFILL }
2969 { &hf_service_info_flags_src_ip_alt_hash,
2970 { "Source IP address in secondary hash", "wccp.service_info_flag.src_ip_alt_hash", FT_BOOLEAN, 32, TFS(&tfs_used_notused), WCCP2_SI_SRC_IP_ALT_HASH,
2971 NULL, HFILL }
2973 { &hf_service_info_flags_dest_ip_alt_hash,
2974 { "Destination IP address in secondary hash", "wccp.service_info_flag.dest_ip_alt_hash", FT_BOOLEAN, 32, TFS(&tfs_used_notused), WCCP2_SI_DST_IP_ALT_HASH,
2975 NULL, HFILL }
2977 { &hf_service_info_flags_src_port_alt_hash,
2978 { "Source port in secondary hash", "wccp.service_info_flag.src_port_alt_hash", FT_BOOLEAN, 32, TFS(&tfs_used_notused), WCCP2_SI_SRC_PORT_ALT_HASH,
2979 NULL, HFILL }
2981 { &hf_service_info_flags_dest_port_alt_hash,
2982 { "Destination port in secondary hash", "wccp.service_info_flag.dest_port_alt_hash", FT_BOOLEAN, 32, TFS(&tfs_used_notused), WCCP2_SI_DST_PORT_ALT_HASH,
2983 NULL, HFILL }
2985 { &hf_service_info_source_port,
2986 { "Source Port", "wccp.service_info_source_port", FT_UINT16, BASE_DEC, NULL, 0x0,
2987 NULL, HFILL }
2989 { &hf_service_info_destination_port,
2990 { "Destination Port", "wccp.service_info_destination_port", FT_UINT16, BASE_DEC, NULL, 0x0,
2991 NULL, HFILL }
2993 { &hf_router_identity_ip,
2994 { "IP Address", "wccp.router_identity.ip", FT_UINT32, BASE_CUSTOM, wccp_fmt_ipadddress, 0x0,
2995 NULL, HFILL }
2997 { &hf_router_identity_receive_id,
2998 { "Received ID", "wccp.router_identity.receive_id", FT_UINT32, BASE_DEC, 0x0, 0x0,
2999 NULL, HFILL }
3001 { &hf_router_identity_send_to_ip,
3002 { "Sent To IP Address", "wccp.router_identity.send_to_ip", FT_UINT32, BASE_CUSTOM, wccp_fmt_ipadddress, 0x0,
3003 NULL, HFILL }
3005 { &hf_router_identity_received_from_num,
3006 { "Number of Received From IP addresses (Webcache to which the message is directed)", "wccp.router.num_recv_ip", FT_UINT32, BASE_DEC, 0x0, 0x0,
3007 NULL, HFILL }
3009 { &hf_web_cache_identity_ip,
3010 { "Web-Cache IP Address", "wccp.web_cache_identity.ip", FT_UINT32, BASE_CUSTOM, wccp_fmt_ipadddress, 0x0,
3011 NULL, HFILL }
3013 { &hf_web_cache_identity_hash_rev,
3014 { "Hash Revision", "wccp.web_cache_identity.hash_rev", FT_UINT16, BASE_DEC, NULL, 0x0,
3015 NULL, HFILL }
3017 { &hf_web_cache_identity_flags,
3018 { "Flags", "wccp.web_cache_identity.flags", FT_UINT16, BASE_HEX, NULL, 0x0,
3019 NULL, HFILL }
3021 { &hf_web_cache_identity_flag_hash_info,
3022 { "Hash information", "wccp.web_cache_identity.flags.hash_info", FT_BOOLEAN, 16,
3023 TFS(&tfs_historical_current), 0x1,
3024 NULL, HFILL }
3026 { &hf_web_cache_identity_flag_assign_type,
3027 { "Assignment Type", "wccp.web_cache_identity.flags.assign_type", FT_UINT16, BASE_HEX,
3028 VALS(&wccp_web_cache_assignment_data_type_val), 0x6,
3029 NULL, HFILL }
3031 { &hf_web_cache_identity_flag_version_request,
3032 { "Version Request", "wccp.web_cache_identity.flags.version_request", FT_BOOLEAN, 16,
3033 TFS(&tfs_version_min_max), 0x8,
3034 NULL, HFILL }
3036 { &hf_mask_value_set_element_value_element_num,
3037 { "Number of Value Elements", "wccp.mask_value_set_selement.value_element_num", FT_UINT32, BASE_DEC, 0x0, 0x0,
3038 NULL, HFILL }
3040 { &hf_assignment_weight,
3041 { "Assignment Weight", "wccp.assignment_weight", FT_UINT16, BASE_DEC, NULL, 0x0,
3042 NULL, HFILL }
3044 { &hf_assignment_status,
3045 { "Status", "wccp.assignment_status", FT_UINT16, BASE_HEX, NULL, 0x0,
3046 NULL, HFILL }
3048 { &hf_assignment_key_ip,
3049 { "Assignment Key IP Address", "wccp.assignment_key.ip", FT_UINT32, BASE_CUSTOM, wccp_fmt_ipadddress, 0x0,
3050 NULL, HFILL }
3052 { &hf_assignment_key_change_num,
3053 { "Assignment Key Change Number", "wccp.assignment_key.change_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3054 NULL, HFILL }
3056 { &hf_router_view_member_change_num,
3057 { "Member Change Number", "wccp.router_view.member_change_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3058 NULL, HFILL }
3060 { &hf_router_router_num,
3061 { "Number of Routers", "wccp.router_view.router_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3062 NULL, HFILL }
3064 { &hf_router_identity_router_ip,
3065 { "Router IP Address", "wccp.router_identity.router_ip", FT_UINT32, BASE_CUSTOM, wccp_fmt_ipadddress, 0x0,
3066 NULL, HFILL }
3068 { &hf_router_identity_received_from_ip,
3069 { "Received From IP Address/Target Web Cache IP", "wccp.router_identity.received_from_ip", FT_UINT32, BASE_CUSTOM, wccp_fmt_ipadddress, 0x0,
3070 NULL, HFILL }
3072 { &hf_wc_view_info_change_num,
3073 { "Change Number", "wccp.wc_view_info.change_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3074 NULL, HFILL }
3076 { &hf_wc_view_info_router_ip,
3077 { "Router IP", "wccp.wc_view_info.router_ip", FT_UINT32, BASE_CUSTOM, wccp_fmt_ipadddress, 0x0,
3078 NULL, HFILL }
3080 { &hf_wc_view_info_wc_ip,
3081 { "Web Cache IP", "wccp.wc_view_info.wc_ip", FT_UINT32, BASE_CUSTOM, wccp_fmt_ipadddress, 0x0,
3082 NULL, HFILL }
3084 { &hf_wc_view_router_num,
3085 { "Number of Routers", "wccp.wc_view_info.router_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3086 NULL, HFILL }
3088 { &hf_wc_view_wc_num,
3089 { "Number of Web Caches", "wccp.wc_view_info.wc_num", FT_UINT32, BASE_DEC, 0x0, 0x0,
3090 NULL, HFILL }
3092 { &hf_wc_identity_ip_address,
3093 { "Web Cache Identity", "wccp.hf_wc_identity_ip_address", FT_UINT32, BASE_CUSTOM, wccp_fmt_ipadddress, 0x0,
3094 "The IP identifying the Web Cache", HFILL }
3096 { &hf_router_assignment_element_change_num,
3097 { "Change Number", "wccp.router_assignment_element.change_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3098 NULL, HFILL }
3100 { &hf_assignment_info_router_num,
3101 { "Number of Routers", "wccp.assignment_info.router_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3102 NULL, HFILL }
3104 { &hf_assignment_info_router_ip,
3105 { "Router IP", "wccp.assignment_info.router_ip", FT_UINT32, BASE_CUSTOM, wccp_fmt_ipadddress, 0x0,
3106 NULL, HFILL }
3108 { &hf_hash_buckets_assignment_wc_num,
3109 { "Number of WC", "wccp.hash_buckets_assignment.wc_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3110 NULL, HFILL }
3112 { &hf_hash_buckets_assignment_wc_ip,
3113 { "WC IP", "wccp.hash_buckets_assignment.wc_ip", FT_UINT32, BASE_CUSTOM, wccp_fmt_ipadddress, 0x0,
3114 NULL, HFILL }
3116 { &hf_router_view_ip,
3117 { "Router IP Address", "wccp.router_view.ip", FT_UINT32, BASE_CUSTOM, wccp_fmt_ipadddress, 0x0,
3118 NULL, HFILL }
3120 { &hf_router_query_info_ip,
3121 { "Web-Cache Identity Element IP address", "wccp.router_query_info.ip", FT_UINT32, BASE_CUSTOM, wccp_fmt_ipadddress, 0x0,
3122 NULL, HFILL }
3124 { &hf_router_query_info_send_to_ip,
3125 { "Sent To IP Address", "wccp.router_query_info.send_to_ip", FT_UINT32, BASE_CUSTOM, wccp_fmt_ipadddress, 0x0,
3126 NULL, HFILL }
3128 { &hf_router_query_info_target_ip,
3129 { "Target IP Address", "wccp.router_query_info.target_ip", FT_UINT32, BASE_CUSTOM, wccp_fmt_ipadddress, 0x0,
3130 NULL, HFILL }
3132 { &hf_capability_element_type,
3133 { "Type", "wccp.capability_element.type", FT_UINT16, BASE_DEC, VALS(capability_type_vals), 0x0,
3134 NULL, HFILL }
3136 { &hf_capability_element_length,
3137 { "Value Length", "wccp.capability_element.length", FT_UINT16, BASE_DEC, NULL, 0x0,
3138 NULL, HFILL }
3140 { &hf_capability_info_value,
3141 { "Value", "wccp.capability_info.value", FT_UINT32, BASE_HEX, NULL, 0x0,
3142 NULL, HFILL }
3144 { &hf_capability_forwarding_method_flag_gre,
3145 { "GRE-encapsulated", "wccp.capability_info.forwarding_method_flag.gre", FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), WCCP2_FORWARDING_METHOD_GRE,
3146 NULL, HFILL }
3148 { &hf_capability_forwarding_method_flag_l2,
3149 { "L2 rewrite", "wccp.capability_info.forwarding_method_flag.l2", FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), WCCP2_FORWARDING_METHOD_L2,
3150 NULL, HFILL }
3152 { &hf_capability_assignment_method_flag_hash,
3153 { "Hash", "wccp.capability_info.assignment_method_flag.hash", FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), WCCP2_ASSIGNMENT_METHOD_HASH,
3154 NULL, HFILL }
3156 { &hf_capability_assignment_method_flag_mask,
3157 { "Mask", "wccp.capability_info.assignment_method_flag.mask", FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), WCCP2_ASSIGNMENT_METHOD_MASK,
3158 NULL, HFILL }
3160 { &hf_capability_return_method_flag_gre,
3161 { "GRE-encapsulated", "wccp.capability_info.return_method_flag.gre", FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), WCCP2_PACKET_RETURN_METHOD_GRE,
3162 NULL, HFILL }
3164 { &hf_capability_return_method_flag_l2,
3165 { "L2 rewrite", "wccp.capability_info.return_method_flag.l2", FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), WCCP2_PACKET_RETURN_METHOD_L2,
3166 NULL, HFILL }
3168 { &hf_capability_transmit_t,
3169 { "Message interval in milliseconds", "wccp.capability.transmit_t", FT_UINT16, BASE_DEC, NULL, 0x0,
3170 NULL, HFILL }
3172 { &hf_capability_transmit_t_upper_limit,
3173 { "Message interval upper limit in milliseconds", "wccp.capability.transmit_t.upper_limit", FT_UINT16, BASE_DEC, NULL, 0x0,
3174 NULL, HFILL }
3176 { &hf_capability_transmit_t_lower_limit,
3177 { "Message interval lower limit in milliseconds", "wccp.capability.transmit_t.upper_limit", FT_UINT16, BASE_DEC, NULL, 0x0,
3178 NULL, HFILL }
3180 { &hf_capability_timer_scale_timeout_scale,
3181 { "Timer scale", "wccp.capability.timer_scale.timeout_scale", FT_UINT8, BASE_DEC, NULL, 0x0,
3182 NULL, HFILL }
3184 { &hf_capability_timer_scale_timeout_scale_upper_limit,
3185 { "Timer scale upper limit", "wccp.capability.timer_scale.timeout_scale.upper_limit", FT_UINT8, BASE_DEC, NULL, 0x0,
3186 NULL, HFILL }
3188 { &hf_capability_timer_scale_timeout_scale_lower_limit,
3189 { "Timer scale lower limit", "wccp.capability.timer_scale.timeout_scale.lower_limit", FT_UINT8, BASE_DEC, NULL, 0x0,
3190 NULL, HFILL }
3192 { &hf_capability_timer_scale_ra_timer_scale,
3193 { "RA Timer scale", "wccp.capability.timer_scale.ra_timer_scale", FT_UINT8, BASE_DEC, NULL, 0x0,
3194 NULL, HFILL }
3196 { &hf_capability_timer_scale_ra_scale_upper_limit,
3197 { "RA Timer scale upper limit", "wccp.capability.timer_scale.ra_timer_scale.upper_limit", FT_UINT8, BASE_DEC, NULL, 0x0,
3198 NULL, HFILL }
3200 { &hf_capability_timer_scale_ra_scale_lower_limit,
3201 { "RA Timer scale lower limit", "wccp.capability.timer_scale.ra_timer_scale.lower_limit", FT_UINT8, BASE_DEC, NULL, 0x0,
3202 NULL, HFILL }
3204 { &hf_value_element_src_ip,
3205 { "Source Address", "wccp.value_element.src_ip", FT_UINT32, BASE_CUSTOM, wccp_fmt_ipadddress, 0x0,
3206 NULL, HFILL }
3208 { &hf_value_element_dest_ip,
3209 { "Destination Address", "wccp.value_element.dest_ip", FT_UINT32, BASE_CUSTOM, wccp_fmt_ipadddress, 0x0,
3210 NULL, HFILL }
3212 { &hf_value_element_src_port,
3213 { "Source Port", "wccp.value_element.src_port", FT_UINT16, BASE_DEC, NULL, 0x0,
3214 NULL, HFILL }
3216 { &hf_value_element_dest_port,
3217 { "Destination Port", "wccp.value_element.dest_port", FT_UINT16, BASE_DEC, NULL, 0x0,
3218 NULL, HFILL }
3220 { &hf_value_element_web_cache_ip,
3221 { "Web Cache Address", "wccp.value_element.web_cache_ip", FT_UINT32, BASE_CUSTOM, wccp_fmt_ipadddress, 0x0,
3222 NULL, HFILL }
3224 { &hf_mask_value_set_list_num_elements,
3225 { "Number of elements", "wccp.mask_value_set_list.num_elements", FT_UINT32, BASE_DEC, NULL, 0x0,
3226 NULL, HFILL }
3228 { &hf_mask_element_src_ip,
3229 { "Source Address Mask", "wccp.mask_element.src_ip", FT_UINT32, BASE_HEX, NULL, 0x0,
3230 NULL, HFILL }
3232 { &hf_mask_element_dest_ip,
3233 { "Destination Address Mask", "wccp.mask_element.dest_ip", FT_UINT32, BASE_HEX, NULL, 0x0,
3234 NULL, HFILL }
3236 { &hf_mask_element_src_port,
3237 { "Source Port Mask", "wccp.mask_element.src_port", FT_UINT16, BASE_HEX, NULL, 0x0,
3238 NULL, HFILL }
3240 { &hf_mask_element_dest_port,
3241 { "Destination Port Mask", "wccp.mask_element.dest_port", FT_UINT16, BASE_HEX, NULL, 0x0,
3242 NULL, HFILL }
3244 { &hf_alt_assignment_info_assignment_type,
3245 { "Assignment type", "wccp.alt_assignment_info.assignment_type", FT_UINT16, BASE_DEC, VALS(assignment_type_vals), 0x0,
3246 NULL, HFILL }
3248 { &hf_extended_assignment_data_type,
3249 { "Assignment type", "wccp.extended_assignment_data.type", FT_UINT16, BASE_DEC, VALS(assignment_type_vals), 0x0,
3250 NULL, HFILL }
3252 { &hf_alt_assignment_map_assignment_type,
3253 { "Assignment type", "wccp.alt_assignment_map.assignment_type", FT_UINT16, BASE_DEC, VALS(assignment_type_vals), 0x0,
3254 NULL, HFILL }
3256 { &hf_alt_assignment_map_assignment_length,
3257 { "Assignment length", "wccp.alt_assignment_map.assignment_length", FT_UINT16, BASE_DEC, NULL, 0x0,
3258 NULL, HFILL }
3260 { &hf_alt_assignment_info_assignment_length,
3261 { "Assignment length", "wccp.alt_assignment_info.assignment_length", FT_UINT16, BASE_DEC, NULL, 0x0,
3262 NULL, HFILL }
3264 { &hf_extended_assignment_data_length,
3265 { "Assignment length", "wccp.extended_assignment_data.length", FT_UINT16, BASE_DEC, NULL, 0x0,
3266 NULL, HFILL }
3268 { &hf_alt_assignment_info_num_routers,
3269 { "Number of routers", "wccp.alt_assignment_info.num_routers", FT_UINT32, BASE_DEC, NULL, 0x0,
3270 NULL, HFILL }
3272 { &hf_alt_assignment_mask_value_set_element_num_wc_value_elements,
3273 { "Number of Web-Cache Value Elements", "wccp.alt_assignment_mask_value_set_element.num_wc_value_elements", FT_UINT32, BASE_DEC, NULL, 0x0,
3274 NULL, HFILL }
3276 { &hf_web_cache_value_element_wc_address,
3277 { "Web-Cache Address", "wccp.web_cache_value_element.wc_address", FT_UINT32, BASE_CUSTOM, wccp_fmt_ipadddress, 0x0,
3278 NULL, HFILL }
3280 { &hf_web_cache_value_element_num_values,
3281 { "Number of Valye Sequence Numbers", "wccp.web_cache_value_element.num_values", FT_UINT32, BASE_DEC, NULL, 0x0,
3282 NULL, HFILL }
3284 { &hf_alt_assignment_mask_value_set_list_num_elements,
3285 { "Number of Alternate Mask/Value Set Elements", "wccp.alt_assignment_mask_value_list.num_elements", FT_UINT32, BASE_DEC, NULL, 0x0,
3286 NULL, HFILL }
3288 { &hf_address_table_family,
3289 { "Family Type", "wccp.address_table.family_type", FT_UINT16, BASE_DEC, VALS(wccp_address_family_val), 0x0,
3290 "The WCCP Address Table Family type", HFILL }
3292 { &hf_address_table_address_length,
3293 { "Address Length", "wccp.address_table.address_length", FT_UINT16, BASE_DEC, NULL, 0x0,
3294 "The WCCP Address Table Address Length", HFILL }
3296 { &hf_address_table_length,
3297 { "Length", "wccp.address_table.length", FT_UINT16, BASE_DEC, NULL, 0x0,
3298 "The WCCP Address Table Length", HFILL }
3300 { &hf_address_table_element,
3301 { "Address", "wccp.address_table.element", FT_STRING, BASE_NONE, NULL, 0x0,
3302 NULL, HFILL }
3306 static gint *ett[] = {
3307 &ett_wccp,
3308 &ett_buckets,
3309 &ett_hash_assignment_buckets,
3310 &ett_mask_assignment_data_element,
3311 &ett_alternate_mask_assignment_data_element,
3312 &ett_extended_assigment_data_element,
3313 &ett_table_element,
3314 &ett_hash_flags,
3315 &ett_wc_identity_flags,
3316 &ett_cache_info,
3317 &ett_security_info,
3318 &ett_service_info,
3319 &ett_service_flags,
3320 &ett_service_info_ports,
3321 &ett_wc_view_info_router_element,
3322 &ett_router_identity_info,
3323 &ett_wc_identity_element,
3324 &ett_wc_identity_info,
3325 &ett_router_view_info,
3326 &ett_wc_view_info,
3327 &ett_query_info,
3328 &ett_router_assignment_element,
3329 &ett_hash_buckets_assignment_wc_element,
3330 &ett_hash_buckets_assignment_buckets,
3331 &ett_router_alt_assignment_element,
3332 &ett_router_assignment_info,
3333 &ett_capabilities_info,
3334 &ett_capability_element,
3335 &ett_capability_forwarding_method,
3336 &ett_capability_assignment_method,
3337 &ett_capability_return_method,
3338 &ett_capability_transmit_t,
3339 &ett_capability_timer_scale,
3340 &ett_mv_set_list,
3341 &ett_mv_set_element,
3342 &ett_mv_set_value_list,
3343 &ett_alternate_mv_set_element_list,
3344 &ett_web_cache_value_element_list,
3345 &ett_alternate_mv_set_element,
3346 &ett_value_element,
3347 &ett_alt_assignment_info,
3348 &ett_alt_assignment_map,
3349 &ett_assignment_map,
3350 &ett_address_table,
3351 &ett_unknown_info,
3352 &ett_alternate_mask_value_set,
3353 &ett_alternate_mask_value_set_element,
3354 &ett_command_extension,
3357 static ei_register_info ei[] = {
3358 { &ei_wccp_missing_security_info, { "wccp.missing.security_info", PI_PROTOCOL, PI_ERROR, "This message should contain a Security Info component, but it is missing", EXPFILL }},
3359 { &ei_wccp_missing_service_info, { "wccp.missing.service_info", PI_PROTOCOL, PI_ERROR, "This message should contain a Service Info component, but it is missing", EXPFILL }},
3360 { &ei_wccp_missing_wc_id_info, { "wccp.missing.wc_id_info", PI_PROTOCOL, PI_ERROR, "This message should contain a Web-Cache Identity Info component, but it is missing", EXPFILL }},
3361 { &ei_wccp_missing_router_id_info, { "wccp.missing.router_id_info", PI_PROTOCOL, PI_ERROR, "This message should contain a Router Identity Info component, but it is missing", EXPFILL }},
3362 { &ei_wccp_missing_query_info, { "wccp.missing.query_info", PI_PROTOCOL, PI_ERROR, "This message should contain a Query Info component, but it is missing", EXPFILL }},
3363 { &ei_wccp_missing_wc_view_info, { "wccp.missing.wc_view_info", PI_PROTOCOL, PI_ERROR, "This message should contain a Web-Cache View Info component, but it is missing", EXPFILL }},
3364 { &ei_wccp_missing_rtr_view_info, { "wccp.missing.rtr_view_info", PI_PROTOCOL, PI_ERROR, "This message should contain a Router View Info component, but it is missing", EXPFILL }},
3365 { &ei_wccp_missing_assignment, { "wccp.missing.assignment", PI_PROTOCOL, PI_ERROR, "This message should contain a Alternate Assignment, Assignment Map, Assignment Info or "
3366 "Alternative Assignment Map component, but it is missing", EXPFILL }},
3367 { &ei_wccp_contains_redirect_assignment, { "wccp.contains.redirect_assignment", PI_PROTOCOL, PI_ERROR, "This message contains a Assignment Info component, but it should not", EXPFILL }},
3368 { &ei_wccp_contains_router_id_info, { "wccp.contains.router_id_info", PI_PROTOCOL, PI_ERROR, "This message contains a Router Identity Info component, but it should not", EXPFILL }},
3369 { &ei_wccp_contains_rtr_view_info, { "wccp.contains.rtr_view_info", PI_PROTOCOL, PI_ERROR, "This message contains a Router View Info component, but it should not", EXPFILL }},
3370 { &ei_wccp_contains_query_info, { "wccp.contains.query_info", PI_PROTOCOL, PI_ERROR, "This message contains a Query Info component, but it should not", EXPFILL }},
3371 { &ei_wccp_contains_alt_assignment, { "wccp.contains.alt_assignment", PI_PROTOCOL, PI_ERROR, "This message contains a Alternate Assignment component, but it should not", EXPFILL }},
3372 { &ei_wccp_contains_assign_map, { "wccp.contains.assign_map", PI_PROTOCOL, PI_ERROR, "This message contains a Assignment Map component, but it should not", EXPFILL }},
3373 { &ei_wccp_contains_alt_assignment_map, { "wccp.contains.alt_assignment_map", PI_PROTOCOL, PI_ERROR, "This message contains a Alternative Assignment Map component, but it should not", EXPFILL }},
3374 { &ei_wccp_contains_wc_id_info, { "wccp.contains.wc_id_info", PI_PROTOCOL, PI_ERROR, "This message contains a Web-Cache Identity Info component, but it should not", EXPFILL }},
3375 { &ei_wccp_contains_wc_view_info, { "wccp.contains.wc_view_info", PI_PROTOCOL, PI_ERROR, "This message contains a Web-Cache View Info component, but it should not", EXPFILL }},
3376 { &ei_wccp_contains_capabilities_info, { "wccp.contains.capabilities_info", PI_PROTOCOL, PI_ERROR, "This message contains a Capabilities Info component, but it should not", EXPFILL }},
3377 { &ei_wccp_contains_command_extension, { "wccp.contains.command_extension", PI_PROTOCOL, PI_ERROR, "This message contains a Command Extension component, but it should not", EXPFILL }},
3378 { &ei_wccp_assignment_length_bad, { "wccp.assignment_length_bad", PI_PROTOCOL, PI_ERROR, "Assignment length bad", EXPFILL }},
3379 { &ei_wccp_length_bad, { "wccp.length_bad", PI_PROTOCOL, PI_ERROR, "Length bad", EXPFILL }},
3380 { &ei_wccp_service_info_priority_nonzero, { "wccp.service_info_priority.nonzero", PI_PROTOCOL, PI_WARN, "The priority must be zero for well-known services.", EXPFILL }},
3381 { &ei_wccp_service_info_protocol_nonzero, { "wccp.service_info_protocol.nonzero", PI_PROTOCOL, PI_WARN, "The protocol must be zero for well-known services.", EXPFILL }},
3382 { &ei_wccp_router_identity_receive_id_zero, { "wccp.router_identity.receive_id.zero", PI_PROTOCOL, PI_WARN, "Receive ID shouldn't be 0", EXPFILL }},
3383 { &ei_wccp_web_cache_identity_hash_rev_zero, { "wccp.web_cache_identity.hash_rev.zero", PI_PROTOCOL, PI_WARN, "Should be 0 (6.4)", EXPFILL }},
3384 { &ei_wccp_address_table_family_unknown, { "wccp.address_table.family_type.unknown", PI_PROTOCOL, PI_ERROR, "Unknown address family", EXPFILL }},
3385 { &ei_wccp_capability_element_length, { "wccp.capability_element.length.invalid", PI_PROTOCOL, PI_WARN, "Value Length invalid", EXPFILL }},
3388 expert_module_t* expert_wccp;
3390 proto_wccp = proto_register_protocol("Web Cache Communication Protocol",
3391 "WCCP", "wccp");
3392 proto_register_field_array(proto_wccp, hf, array_length(hf));
3393 proto_register_subtree_array(ett, array_length(ett));
3394 expert_wccp = expert_register_protocol(proto_wccp);
3395 expert_register_field_array(expert_wccp, ei, array_length(ei));
3398 void
3399 proto_reg_handoff_wccp(void)
3401 dissector_handle_t wccp_handle;
3403 wccp_handle = new_create_dissector_handle(dissect_wccp, proto_wccp);
3404 dissector_add_uint("udp.port", UDP_PORT_WCCP, wccp_handle);
3408 * Editor modelines - http://www.wireshark.org/tools/modelines.html
3410 * Local variables:
3411 * c-basic-offset: 2
3412 * tab-width: 8
3413 * indent-tabs-mode: nil
3414 * End:
3416 * vi: set shiftwidth=2 tabstop=8 expandtab:
3417 * :indentSize=2:tabSize=8:noTabs=true: