2 * Routines for Web Cache Communication Protocol dissection
3 * Jerry Talkington <jtalkington@users.sourceforge.net>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 #include <epan/packet.h>
28 #include <epan/to_str.h>
29 #include <epan/wmem/wmem.h>
30 #include <epan/ipproto.h>
31 #include <epan/expert.h>
32 #include <epan/ipv6-utils.h>
33 #include <epan/ipv4.h>
34 #include "packet-wccp.h"
36 void proto_register_wccp(void);
37 void proto_reg_handoff_wccp(void);
39 static int proto_wccp = -1;
40 static int hf_wccp_message_type = -1; /* the message type */
41 static int hf_wccp_version = -1; /* protocol version */
42 static int hf_message_header_version = -1;
43 static int hf_hash_revision = -1; /* the version of the hash */
44 static int hf_change_num = -1; /* change number */
45 static int hf_hash_flag = -1;
46 static int hf_hash_flag_u = -1;
47 static int hf_recvd_id = -1;
48 static int hf_wc_num = -1;
49 static int hf_wc_view_wc_num = -1;
50 static int hf_cache_ip = -1;
51 static int hf_message_header_length = -1;
52 static int hf_item_type = -1;
53 static int hf_item_length = -1;
54 static int hf_item_data = -1;
55 static int hf_security_info_option = -1;
56 static int hf_security_info_md5_checksum = -1;
57 static int hf_command_element_type = -1;
58 static int hf_command_element_length = -1;
59 static int hf_command_element_shutdown_ip = -1;
60 static int hf_service_info_type = -1;
61 static int hf_service_info_id_standard = -1;
62 static int hf_service_info_id_dynamic = -1;
63 static int hf_service_info_priority = -1;
64 static int hf_service_info_protocol = -1;
65 static int hf_service_info_flags = -1;
66 static int hf_service_info_flags_src_ip_hash = -1;
67 static int hf_service_info_flags_dest_ip_hash = -1;
68 static int hf_service_info_flags_src_port_hash = -1;
69 static int hf_service_info_flags_dest_port_hash = -1;
70 static int hf_service_info_flags_ports_defined = -1;
71 static int hf_service_info_flags_ports_source = -1;
72 static int hf_service_info_flags_redirect_only_protocol_0 = -1;
73 static int hf_service_info_flags_src_ip_alt_hash = -1;
74 static int hf_service_info_flags_dest_ip_alt_hash = -1;
75 static int hf_service_info_flags_src_port_alt_hash = -1;
76 static int hf_service_info_flags_dest_port_alt_hash = -1;
77 static int hf_service_info_source_port = -1;
78 static int hf_service_info_destination_port = -1;
79 static int hf_router_identity_ip = -1;
80 static int hf_router_identity_receive_id = -1;
81 static int hf_router_identity_send_to_ip = -1;
82 static int hf_router_identity_received_from_num = -1;
83 static int hf_web_cache_identity_ip = -1;
84 static int hf_web_cache_identity_hash_rev = -1;
85 static int hf_web_cache_identity_flags = -1;
86 static int hf_web_cache_identity_flag_hash_info = -1;
87 static int hf_web_cache_identity_flag_assign_type = -1;
88 static int hf_web_cache_identity_flag_version_request = -1;
89 static int hf_mask_value_set_element_value_element_num = -1;
90 static int hf_assignment_weight = -1;
91 static int hf_assignment_status = -1;
92 static int hf_assignment_key_ip = -1;
93 static int hf_assignment_key_change_num = -1;
94 static int hf_router_view_member_change_num = -1;
95 static int hf_router_router_num = -1;
96 static int hf_router_identity_router_ip = -1;
97 static int hf_wc_view_info_change_num = -1;
98 static int hf_wc_view_info_router_ip = -1;
99 static int hf_wc_view_info_wc_ip = -1;
100 static int hf_wc_view_router_num = -1;
101 static int hf_wc_identity_ip_address = -1;
102 static int hf_router_identity_received_from_ip = -1;
103 static int hf_router_assignment_element_change_num = -1;
104 static int hf_assignment_info_router_num = -1;
105 static int hf_hash_buckets_assignment_wc_num = -1;
106 static int hf_hash_buckets_assignment_wc_ip = -1;
107 static int hf_assignment_info_router_ip = -1;
108 static int hf_router_view_ip = -1;
109 static int hf_router_query_info_ip = -1;
110 static int hf_router_query_info_send_to_ip = -1;
111 static int hf_router_query_info_target_ip = -1;
112 static int hf_capability_element_type = -1;
113 static int hf_capability_element_length = -1;
114 static int hf_capability_info_value = -1;
115 static int hf_capability_forwarding_method_flag_gre = -1;
116 static int hf_capability_forwarding_method_flag_l2 = -1;
117 static int hf_capability_assignment_method_flag_hash = -1;
118 static int hf_capability_assignment_method_flag_mask = -1;
119 static int hf_capability_return_method_flag_gre = -1;
120 static int hf_capability_return_method_flag_l2 = -1;
121 static int hf_capability_transmit_t = -1;
122 static int hf_capability_transmit_t_upper_limit = -1;
123 static int hf_capability_transmit_t_lower_limit = -1;
124 static int hf_capability_timer_scale_timeout_scale = -1;
125 static int hf_capability_timer_scale_ra_timer_scale = -1;
126 static int hf_capability_timer_scale_timeout_scale_upper_limit = -1;
127 static int hf_capability_timer_scale_timeout_scale_lower_limit = -1;
128 static int hf_capability_timer_scale_ra_scale_upper_limit = -1;
129 static int hf_capability_timer_scale_ra_scale_lower_limit = -1;
130 static int hf_value_element_src_ip = -1;
131 static int hf_value_element_dest_ip = -1;
132 static int hf_value_element_src_port = -1;
133 static int hf_value_element_dest_port = -1;
134 static int hf_value_element_web_cache_ip = -1;
135 static int hf_mask_value_set_list_num_elements = -1;
136 static int hf_mask_element_src_ip = -1;
137 static int hf_mask_element_dest_ip = -1;
138 static int hf_mask_element_src_port = -1;
139 static int hf_mask_element_dest_port = -1;
140 static int hf_alt_assignment_info_assignment_type = -1;
141 static int hf_extended_assignment_data_type = -1;
142 static int hf_alt_assignment_info_assignment_length = -1;
143 static int hf_alt_assignment_map_assignment_type = -1;
144 static int hf_alt_assignment_map_assignment_length = -1;
145 static int hf_extended_assignment_data_length = -1;
146 static int hf_alt_assignment_info_num_routers = -1;
147 static int hf_alt_assignment_mask_value_set_element_num_wc_value_elements = -1;
148 static int hf_web_cache_value_element_wc_address = -1;
149 static int hf_web_cache_value_element_num_values = -1;
150 static int hf_alt_assignment_mask_value_set_list_num_elements = -1;
151 static int hf_address_table_family = -1;
152 static int hf_address_table_address_length = -1;
153 static int hf_address_table_length = -1;
154 static int hf_address_table_element = -1;
156 static gint ett_wccp = -1;
157 static gint ett_buckets = -1;
158 static gint ett_hash_assignment_buckets = -1;
159 static gint ett_mask_assignment_data_element = -1;
160 static gint ett_alternate_mask_assignment_data_element = -1;
161 static gint ett_extended_assigment_data_element = -1;
162 static gint ett_table_element = -1;
163 static gint ett_hash_flags = -1;
164 static gint ett_wc_identity_flags = -1;
165 static gint ett_cache_info = -1;
166 static gint ett_security_info = -1;
167 static gint ett_service_info = -1;
168 static gint ett_service_flags = -1;
169 static gint ett_service_info_ports = -1;
170 static gint ett_wc_view_info_router_element = -1;
171 static gint ett_router_identity_info = -1;
172 static gint ett_wc_identity_element = -1;
173 static gint ett_wc_identity_info = -1;
174 static gint ett_router_view_info = -1;
175 static gint ett_wc_view_info = -1;
176 static gint ett_router_assignment_element = -1;
177 static gint ett_hash_buckets_assignment_wc_element=-1;
178 static gint ett_hash_buckets_assignment_buckets=-1;
179 static gint ett_router_alt_assignment_element = -1;
180 static gint ett_router_assignment_info = -1;
181 static gint ett_query_info = -1;
182 static gint ett_capabilities_info = -1;
183 static gint ett_capability_element = -1;
184 static gint ett_capability_forwarding_method = -1;
185 static gint ett_capability_assignment_method = -1;
186 static gint ett_capability_return_method = -1;
187 static gint ett_capability_transmit_t = -1;
188 static gint ett_capability_timer_scale = -1;
189 static gint ett_alt_assignment_info = -1;
190 static gint ett_alt_assignment_map = -1;
191 static gint ett_address_table = -1;
192 static gint ett_assignment_map = -1;
193 static gint ett_command_extension = -1;
194 static gint ett_alternate_mask_value_set=-1;
195 static gint ett_alternate_mask_value_set_element=-1;
196 static gint ett_mv_set_list = -1;
197 static gint ett_mv_set_element = -1;
198 static gint ett_mv_set_value_list = -1;
199 static gint ett_alternate_mv_set_element_list = -1;
200 static gint ett_web_cache_value_element_list = -1;
201 static gint ett_alternate_mv_set_element = -1;
202 static gint ett_value_element = -1;
203 static gint ett_unknown_info = -1;
205 static expert_field ei_wccp_missing_security_info = EI_INIT;
206 static expert_field ei_wccp_missing_service_info = EI_INIT;
207 static expert_field ei_wccp_missing_wc_id_info = EI_INIT;
208 static expert_field ei_wccp_missing_router_id_info = EI_INIT;
209 static expert_field ei_wccp_missing_query_info = EI_INIT;
210 static expert_field ei_wccp_missing_wc_view_info = EI_INIT;
211 static expert_field ei_wccp_missing_rtr_view_info = EI_INIT;
212 static expert_field ei_wccp_contains_redirect_assignment = EI_INIT;
213 static expert_field ei_wccp_contains_router_id_info = EI_INIT;
214 static expert_field ei_wccp_contains_rtr_view_info = EI_INIT;
215 static expert_field ei_wccp_contains_query_info = EI_INIT;
216 static expert_field ei_wccp_contains_alt_assignment = EI_INIT;
217 static expert_field ei_wccp_contains_assign_map = EI_INIT;
218 static expert_field ei_wccp_contains_alt_assignment_map = EI_INIT;
219 static expert_field ei_wccp_contains_wc_id_info = EI_INIT;
220 static expert_field ei_wccp_contains_wc_view_info = EI_INIT;
221 static expert_field ei_wccp_contains_capabilities_info = EI_INIT;
222 static expert_field ei_wccp_contains_command_extension = EI_INIT;
223 static expert_field ei_wccp_missing_assignment = EI_INIT;
224 static expert_field ei_wccp_assignment_length_bad = EI_INIT;
225 static expert_field ei_wccp_length_bad = EI_INIT;
226 static expert_field ei_wccp_service_info_priority_nonzero = EI_INIT;
227 static expert_field ei_wccp_service_info_protocol_nonzero = EI_INIT;
228 static expert_field ei_wccp_router_identity_receive_id_zero = EI_INIT;
229 static expert_field ei_wccp_web_cache_identity_hash_rev_zero = EI_INIT;
230 static expert_field ei_wccp_address_table_family_unknown = EI_INIT;
231 static expert_field ei_wccp_capability_element_length = EI_INIT;
236 * http://tools.ietf.org/html/draft-forster-wrec-wccp-v1-00
238 * is a copy of the now-expired Internet-Draft for WCCP 1.0.
242 * http://tools.ietf.org/id/draft-wilson-wrec-wccp-v2-01.txt
244 * is an Internet-Draft for WCCP 2.0.
246 * http://tools.ietf.org/html/draft-mclaggan-wccp-v2rev1
248 * is the current draft for WCCP 2.01
252 /* This is NOT IANA assigned */
253 #define UDP_PORT_WCCP 2048
256 #define WCCPv2 0x0200
257 #define WCCPv2r1 0x0201
258 #define WCCP_HERE_I_AM 7
259 #define WCCP_I_SEE_YOU 8
260 #define WCCP_ASSIGN_BUCKET 9
261 #define WCCP2_HERE_I_AM 10
262 #define WCCP2_I_SEE_YOU 11
263 #define WCCP2_REDIRECT_ASSIGN 12
264 #define WCCP2_REMOVAL_QUERY 13
266 static const value_string wccp_type_vals[] = {
267 { WCCP_HERE_I_AM, "1.0 Here I am" },
268 { WCCP_I_SEE_YOU, "1.0 I see you" },
269 { WCCP_ASSIGN_BUCKET, "1.0 Assign bucket" },
270 { WCCP2_HERE_I_AM, "2.0 Here I am" },
271 { WCCP2_I_SEE_YOU, "2.0 I see you" },
272 { WCCP2_REDIRECT_ASSIGN, "2.0 Redirect assign" },
273 { WCCP2_REMOVAL_QUERY, "2.0 Removal query" },
277 static const value_string wccp_version_val[] = {
284 const true_false_string tfs_defined_not_defined = { "Defined", "Not defined" };
285 const true_false_string tfs_src_dest_port = { "Source port", "Destination port" };
286 const true_false_string tfs_redirect_protocol0 = { "Redirect only protocol 0 (IP)", "Redirect all traffic" };
287 const true_false_string tfs_historical_current = { "Historical", "Current" };
288 const true_false_string tfs_version_min_max = {"WCCP version set is maximum supported by CE", "WCCP version set is minimum supported by CE"};
290 static const value_string wccp_address_family_val[] = {
298 #define WCCP2_HASH_ASSIGNMENT_TYPE 0
299 #define WCCP2_MASK_ASSIGNMENT_TYPE 1
300 #define WCCP2r1_ALT_MASK_ASSIGNMENT_TYPE 2
301 #define WCCP2r1_ASSIGNMENT_WEIGHT_STATUS 3
303 static const value_string assignment_type_vals[] = {
304 { WCCP2_HASH_ASSIGNMENT_TYPE, "Hash" },
305 { WCCP2_MASK_ASSIGNMENT_TYPE, "Mask" },
306 { WCCP2r1_ALT_MASK_ASSIGNMENT_TYPE, "WCCP2r1 Alternate Mask"},
307 { WCCP2r1_ASSIGNMENT_WEIGHT_STATUS, "WCCP2r1 Assignment Weight Status"},
311 #define HASH_INFO_SIZE (4*(1+8+1))
313 #define WCCP2_SECURITY_INFO 0
314 #define WCCP2_SERVICE_INFO 1
315 #define WCCP2_ROUTER_ID_INFO 2
316 #define WCCP2_WC_ID_INFO 3
317 #define WCCP2_RTR_VIEW_INFO 4
318 #define WCCP2_WC_VIEW_INFO 5
319 #define WCCP2_REDIRECT_ASSIGNMENT 6
320 #define WCCP2_QUERY_INFO 7
321 #define WCCP2_CAPABILITIES_INFO 8
322 #define WCCP2_ALT_ASSIGNMENT 13
323 #define WCCP2_ASSIGN_MAP 14
324 #define WCCP2_COMMAND_EXTENSION 15
325 /* WCCP 2 r1 additions: */
326 #define WCCP2r1_ALT_ASSIGNMENT_MAP 16
327 #define WCCP2r1_ADDRESS_TABLE 17
329 static const value_string info_type_vals[] = {
330 { WCCP2_SECURITY_INFO, "Security Info" },
331 { WCCP2_SERVICE_INFO, "Service Info" },
332 { WCCP2_ROUTER_ID_INFO, "Router Identity Info" },
333 { WCCP2_WC_ID_INFO, "Web-Cache Identity Info" },
334 { WCCP2_RTR_VIEW_INFO, "Router View Info" },
335 { WCCP2_WC_VIEW_INFO, "Web-Cache View Info" },
336 { WCCP2_REDIRECT_ASSIGNMENT, "Assignment Info" },
337 { WCCP2_QUERY_INFO, "Router Query Info" },
338 { WCCP2_CAPABILITIES_INFO, "Capabilities Info" },
339 { WCCP2_ALT_ASSIGNMENT, "Alternate Assignment" },
340 { WCCP2_ASSIGN_MAP, "Assignment Map" },
341 { WCCP2_COMMAND_EXTENSION, "Command Extension" },
342 { WCCP2r1_ALT_ASSIGNMENT_MAP, "Alternative Assignment Map" },
343 { WCCP2r1_ADDRESS_TABLE, "Address Table" },
347 const value_string service_id_vals[] = {
352 typedef struct capability_flag {
354 const char *short_name;
361 #define WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_HASH 0
362 #define WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_MASK 1
363 #define WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_NOT_PRESENT 2
364 #define WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_EXTENDED 3
366 static const value_string wccp_web_cache_assignment_data_type_val[] = {
367 { WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_HASH , "Hash Assignment Data Element"},
368 { WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_MASK , "Mask Assignment Data Element"},
369 { WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_NOT_PRESENT , "Assignment Data Element Not Present"},
370 { WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_EXTENDED , "Extended Assignment Data Element"},
374 #define WCCP2_FORWARDING_METHOD 0x01
375 #define WCCP2_ASSIGNMENT_METHOD 0x02
376 #define WCCP2_PACKET_RETURN_METHOD 0x03
377 #define WCCP2_TRANSMIT_T 0x04
378 #define WCCP2_TIMER_SCALE 0x05
380 static const value_string capability_type_vals[] = {
381 { WCCP2_FORWARDING_METHOD, "Forwarding Method" },
382 { WCCP2_ASSIGNMENT_METHOD, "Assignment Method" },
383 { WCCP2_PACKET_RETURN_METHOD, "Packet Return Method" },
384 { WCCP2_TRANSMIT_T, "Transmit_t Message interval values"},
385 { WCCP2_TIMER_SCALE, "Timer_scale Timeout scale values"},
390 /* with version 2.01 we now have a address table which is possibly present */
392 typedef struct wccp_address_table {
396 guint16 table_length;
398 struct e_in6_addr *table_ipv6;
399 } wccp_address_table;
402 wccp_address_table wccp_wccp_address_table;
404 static guint dissect_hash_data(tvbuff_t *tvb, int offset,
405 proto_tree *wccp_tree);
406 static guint dissect_web_cache_list_entry(tvbuff_t *tvb, int offset,
407 int idx, proto_tree *wccp_tree);
408 static int wccp_bucket_info(guint8 bucket_info, proto_tree *bucket_tree,
409 guint32 start, tvbuff_t *tvb, int offset);
410 static const gchar *bucket_name(guint8 bucket);
411 static guint16 dissect_wccp2_header(tvbuff_t *tvb, int offset,
412 proto_tree *wccp_tree);
413 static void dissect_wccp2_info(tvbuff_t *tvb, int offset, guint16 length,
414 packet_info *pinfo, proto_tree *wccp_tree, guint32 wccp_message_type);
416 /* WCCP 2r1 IPv6 utlility functions */
417 static void find_wccp_address_table(tvbuff_t *tvb, int offset, guint16 length,
418 packet_info *pinfo _U_, proto_tree *wccp_tree _U_);
419 /* The V2 dissectors will return the remaining length of the packet
420 and a negative number if there are missing bytes to finish the
422 static gint dissect_wccp2_security_info(tvbuff_t *tvb, int offset, gint lengreth,
423 packet_info *pinfo _U_, proto_tree *info_tree);
424 static gint dissect_wccp2_service_info(tvbuff_t *tvb, int offset, gint length,
425 packet_info *pinfo, proto_tree *info_tree);
426 static gint dissect_wccp2r1_address_table_info(tvbuff_t *tvb, int offset,
427 int length, packet_info *pinfo, proto_tree *info_tree);
428 static gint dissect_wccp2_router_identity_info(tvbuff_t *tvb, int offset, gint length,
429 packet_info *pinfo _U_, proto_tree *info_tree);
430 static gint dissect_wccp2_wc_identity_info(tvbuff_t *tvb, int offset, gint length,
431 packet_info *pinfo _U_, proto_tree *info_tree);
432 static gint dissect_wccp2_router_view_info(tvbuff_t *tvb, int offset, gint length,
433 packet_info *pinfo _U_, proto_tree *info_tree);
434 static gint dissect_wccp2_web_cache_view_info(tvbuff_t *tvb, int offset, gint length,
435 packet_info *pinfo _U_, proto_tree *info_tree);
436 static gint dissect_wccp2_assignment_info(tvbuff_t *tvb, int offset, gint length,
437 packet_info *pinfo _U_, proto_tree *info_tree);
438 static gint dissect_wccp2_hash_buckets_assignment_element(tvbuff_t *tvb, int offset, gint length,
439 packet_info *pinfo, proto_tree *info_tree);
440 static gboolean dissect_wccp2_router_query_info(tvbuff_t *tvb, int offset, gint length,
441 packet_info *pinfo _U_, proto_tree *info_tree);
442 static gint dissect_wccp2_capability_info(tvbuff_t *tvb, int offset, gint length,
443 packet_info *pinfo _U_, proto_tree *info_tree);
444 static gint dissect_wccp2_alternate_assignment_info(tvbuff_t *tvb, int offset, gint length,
445 packet_info *pinfo, proto_tree *info_tree);
446 static gint dissect_wccp2_hash_assignment_info(tvbuff_t *tvb, int offset, gint length,
447 packet_info *pinfo _U_, proto_tree *info_tree);
448 static gint dissect_wccp2_assignment_map(tvbuff_t *tvb, int offset,
449 int length, packet_info *pinfo _U_, proto_tree *info_tree);
450 static gint dissect_wccp2r1_alt_assignment_map_info(tvbuff_t *tvb, int offset,
451 int length, packet_info *pinfo, proto_tree *info_tree);
452 static gint dissect_wccp2_command_extension(tvbuff_t *tvb, int offset,
453 int length, packet_info *pinfo _U_, proto_tree *info_tree);
454 static void dissect_wccp2_router_identity_element(tvbuff_t *tvb, int offset, packet_info *pinfo,
456 static gint dissect_wccp2_web_cache_identity_element(tvbuff_t *tvb, int offset, gint length, packet_info *pinfo,
457 proto_tree *info_tree);
458 static gint dissect_wccp2_hash_assignment_data_element(tvbuff_t *tvb, int offset, gint length, packet_info *pinfo,
459 proto_tree *info_tree);
460 static gint dissect_wccp2_mask_assignment_data_element(tvbuff_t *tvb, int offset, gint length, packet_info *pinfo,
461 proto_tree *info_tree) ;
462 static gint dissect_wccp2_alternate_mask_assignment_data_element(tvbuff_t *tvb, int offset, gint length, packet_info *pinfo,
463 proto_tree *info_tree);
464 static gint dissect_wccp2_assignment_weight_and_status_element(tvbuff_t *tvb, int offset, gint length, packet_info *pinfo,
465 proto_tree *info_tree);
466 static gint dissect_wccp2_extended_assignment_data_element(tvbuff_t *tvb, int offset, gint length, packet_info *pinfo,
467 proto_tree *info_tree);
468 static gint dissect_wccp2_assignment_key_element(tvbuff_t *tvb, int offset, gint length, packet_info *pinfo,
469 proto_tree *info_tree);
470 static void dissect_wccp2_router_assignment_element(tvbuff_t *tvb, int offset, gint length,
471 packet_info *pinfo, proto_tree *info_tree) ;
472 static gint dissect_wccp2_capability_element(tvbuff_t *tvb, int offset, gint length,
473 packet_info *pinfo _U_, proto_tree *info_tree);
474 static gint dissect_wccp2_mask_value_set_list(tvbuff_t *tvb, int offset,
475 int length, packet_info *pinfo, proto_tree *info_tree);
477 /* Utility functions */
478 static gint dissect_wccp2_mask_value_set_element(tvbuff_t *tvb, int offset,
479 gint length, int idx, packet_info *pinfo, proto_tree *info_tree);
480 static gint dissect_wccp2_mask_element(tvbuff_t *tvb, int offset,
481 gint length, packet_info *pinfo, proto_tree *info_tree);
482 static gint dissect_wccp2_value_element(tvbuff_t *tvb, int offset,
483 gint length, int idx, packet_info *pinfo, proto_tree *info_tree);
484 static gint dissect_wccp2_alternate_mask_value_set_list(tvbuff_t *tvb, int offset,
485 gint length, packet_info *pinfo _U_, proto_tree *info_tree);
486 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);
487 static gint dissect_wccp2_web_cache_value_element(tvbuff_t *tvb, int offset,
488 gint length, packet_info *pinfo, proto_tree *info_tree);
489 static const gchar *assignment_bucket_name(guint8 bucket);
490 static void dissect_32_bit_capability_flags(tvbuff_t *tvb, int curr_offset,
491 guint16 capability_val_len, gint ett, const capability_flag *flags,
492 proto_tree *element_tree, proto_item *header);
493 static void dissect_transmit_t_capability(tvbuff_t *tvb, proto_item *te, int curr_offset,
494 guint16 capability_val_len, gint ett, proto_tree *element_tree);
495 static void dissect_timer_scale_capability(tvbuff_t *tvb, int curr_offset,
496 guint16 capability_val_len, gint ett, proto_tree *element_tree);
502 * In WCCP 2.01 addresses are encoded to support IPv6 with 32 bit fields
504 * handle the decoding
508 find_wccp_address_table(tvbuff_t *tvb, int offset, guint16 length,
509 packet_info *pinfo _U_, proto_tree *wccp_tree _U_)
514 /* first clean up: */
515 wccp_wccp_address_table.in_use = FALSE;
516 wccp_wccp_address_table.family = -1;
517 wccp_wccp_address_table.version = -1;
518 wccp_wccp_address_table.table_length = 0;
519 wccp_wccp_address_table.table_ipv4 = (guint32 *) NULL;
520 wccp_wccp_address_table.table_ipv6 = (struct e_in6_addr *)NULL;
522 while (length >= 4) {
523 type = tvb_get_ntohs(tvb, offset);
524 item_length = tvb_get_ntohs(tvb, offset+2);
526 if (item_length > tvb_length_remaining(tvb, offset))
529 if (type == WCCP2r1_ADDRESS_TABLE)
531 dissect_wccp2r1_address_table_info(tvb, offset+4, item_length, NULL, NULL);
532 /* no need to decode the rest */
536 /* check if we _can_ advance */
537 if (length < (item_length+4))
540 offset = offset + item_length + 4;
541 length = length - item_length - 4;
546 /* This function prints the IP or the encoded IP if the table exists */
548 /* at most an IPv6 IP: see
549 http://stackoverflow.com/questions/166132/maximum-length-of-the-textual-representation-of-an-ipv6-address
551 39 = 8 groups of 4 digits with 7 : characters
555 45 = IPv4 tunnel features: 0000:0000:0000:0000:0000:0000:192.168.0.1
558 /* problem here is that the IP is in network byte order for IPv4
562 static void wccp_fmt_ipadddress(gchar *buffer, guint32 host_addr)
564 /* are we using an address table? */
565 if (! wccp_wccp_address_table.in_use)
567 /* no return the IPv4 IP */
568 /* first fix the byte order */
569 guint addr= GUINT32_SWAP_LE_BE(host_addr);
571 ip_to_str_buf( (guint8 *) &addr, buffer, ITEM_LABEL_LENGTH);
576 /* we need to decode the encoded address: */
577 guint16 reserv = (host_addr & 0xFF00) >> 16;
578 guint16 addr_index = (host_addr & 0x00FF);
581 g_snprintf(buffer, ITEM_LABEL_LENGTH, "INVALID: reserved part non zero");
585 /* now check if it's IPv4 or IPv6 we need to print */
586 switch (wccp_wccp_address_table.family) {
590 /* special case: index 0 -> undefined IP */
591 if (addr_index == 0) {
592 g_snprintf(buffer, ITEM_LABEL_LENGTH, "0.0.0.0");
595 /* are we be beyond the end of the table? */
596 if (addr_index > wccp_wccp_address_table.table_length) {
597 g_snprintf(buffer, ITEM_LABEL_LENGTH, "INVALID IPv4 index: %d > %d",
598 addr_index, wccp_wccp_address_table.table_length);
603 if (wccp_wccp_address_table.table_ipv4 != NULL) {
604 ip_to_str_buf( (guint8 *) &(wccp_wccp_address_table.table_ipv4[addr_index-1]), buffer, ITEM_LABEL_LENGTH);
608 g_snprintf(buffer, ITEM_LABEL_LENGTH, "INVALID IPv4 table empty!");
614 /* special case: index 0 -> undefined IP */
615 if (addr_index == 0) {
616 g_snprintf(buffer, ITEM_LABEL_LENGTH, "::");
620 /* are we be beyond the end of the table? */
621 if (addr_index > wccp_wccp_address_table.table_length) {
622 g_snprintf(buffer, ITEM_LABEL_LENGTH, "INVALID IPv6 index: %d > %d",
623 addr_index, wccp_wccp_address_table.table_length);
628 if (wccp_wccp_address_table.table_ipv6 != NULL) {
629 ip6_to_str_buf(&(wccp_wccp_address_table.table_ipv6[addr_index-1]), buffer);
633 g_snprintf(buffer, ITEM_LABEL_LENGTH, "INVALID IPv6 table empty!");
638 g_snprintf(buffer, ITEM_LABEL_LENGTH, "INVALID IP family");
645 #define WCCP_IP_MAX_LENGTH (MAX_IP_STR_LEN > 46 ? MAX_IP_STR_LEN : 46)
648 static const gchar * decode_wccp_encoded_address(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *info_tree _U_)
653 buffer= (char *) wmem_alloc(wmem_packet_scope(), WCCP_IP_MAX_LENGTH+1);
654 host_addr = tvb_get_ntohl(tvb,offset);
656 wccp_fmt_ipadddress(buffer, host_addr);
661 dissect_wccp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
664 proto_tree *wccp_tree = NULL;
665 proto_item *wccp_tree_item;
666 guint32 wccp_message_type;
672 wccp_message_type = tvb_get_ntohl(tvb, offset);
674 /* Check if this is really a WCCP message */
675 if (try_val_to_str(wccp_message_type, wccp_type_vals) == NULL)
678 col_set_str(pinfo->cinfo, COL_PROTOCOL, "WCCP");
680 col_add_str(pinfo->cinfo, COL_INFO, val_to_str(wccp_message_type,
681 wccp_type_vals, "Unknown WCCP message (%u)"));
683 wccp_tree_item = proto_tree_add_item(tree, proto_wccp, tvb, offset, -1, ENC_NA);
684 wccp_tree = proto_item_add_subtree(wccp_tree_item, ett_wccp);
686 proto_tree_add_uint(wccp_tree, hf_wccp_message_type, tvb, offset, 4, wccp_message_type);
689 switch (wccp_message_type) {
692 proto_tree_add_item(wccp_tree, hf_wccp_version, tvb,
693 offset, 4, ENC_BIG_ENDIAN);
695 offset = dissect_hash_data(tvb, offset, wccp_tree);
696 proto_tree_add_item(wccp_tree, hf_recvd_id, tvb, offset,
702 proto_tree_add_item(wccp_tree, hf_wccp_version, tvb,
703 offset, 4, ENC_BIG_ENDIAN);
705 proto_tree_add_item(wccp_tree, hf_change_num, tvb, offset,
708 proto_tree_add_item(wccp_tree, hf_recvd_id, tvb, offset,
711 cache_count = tvb_get_ntohl(tvb, offset);
712 proto_tree_add_uint(wccp_tree, hf_wc_num, tvb, offset, 4, cache_count);
714 for (i = 0; i < cache_count; i++) {
715 offset = dissect_web_cache_list_entry(tvb, offset, i,
720 case WCCP_ASSIGN_BUCKET:
722 * This hasn't been tested, since I don't have any
723 * traces with this in it.
725 * The V1 spec claims that this does, indeed,
726 * have a Received ID field after the type,
727 * rather than a Version field.
729 proto_tree_add_item(wccp_tree, hf_recvd_id, tvb, offset,
732 cache_count = tvb_get_ntohl(tvb, offset);
733 proto_tree_add_uint(wccp_tree, hf_wc_num, tvb, offset, 4, cache_count);
735 for (i = 0; i < cache_count; i++) {
736 ipaddr = tvb_get_ipv4(tvb, offset);
737 proto_tree_add_ipv4_format(wccp_tree,
738 hf_cache_ip, tvb, offset, 4,
740 "Web Cache %d IP Address: %s", i,
741 ip_to_str((guint8 *)&ipaddr));
744 for (i = 0; i < 256; i += 4) {
745 proto_tree_add_text(wccp_tree, tvb, offset, 4,
746 "Buckets %d - %d: %10s %10s %10s %10s",
748 bucket_name(tvb_get_guint8(tvb, offset)),
749 bucket_name(tvb_get_guint8(tvb, offset+1)),
750 bucket_name(tvb_get_guint8(tvb, offset+2)),
751 bucket_name(tvb_get_guint8(tvb, offset+3)));
756 case WCCP2_HERE_I_AM:
757 case WCCP2_I_SEE_YOU:
758 case WCCP2_REMOVAL_QUERY:
759 case WCCP2_REDIRECT_ASSIGN:
760 default: /* assume unknown packets are v2 */
761 length = dissect_wccp2_header(tvb, offset, wccp_tree);
763 dissect_wccp2_info(tvb, offset, length, pinfo, wccp_tree, wccp_message_type);
767 return tvb_length(tvb);
771 dissect_hash_data(tvbuff_t *tvb, int offset, proto_tree *wccp_tree)
773 proto_item *bucket_item;
774 proto_tree *bucket_tree;
776 proto_tree *field_tree;
781 proto_tree_add_item(wccp_tree, hf_hash_revision, tvb, offset, 4,
785 bucket_item = proto_tree_add_text(wccp_tree, tvb, offset, 32,
787 bucket_tree = proto_item_add_subtree(bucket_item, ett_buckets);
789 for (i = 0, n = 0; i < 32; i++) {
790 bucket_info = tvb_get_guint8(tvb, offset);
791 n = wccp_bucket_info(bucket_info, bucket_tree, n, tvb, offset);
794 tf = proto_tree_add_item(wccp_tree, hf_hash_flag, tvb, offset, 4, ENC_BIG_ENDIAN);
795 field_tree = proto_item_add_subtree(tf, ett_hash_flags);
796 proto_tree_add_item(field_tree, hf_hash_flag_u, tvb, offset, 4, ENC_BIG_ENDIAN);
802 dissect_web_cache_list_entry(tvbuff_t *tvb, int offset, int idx,
803 proto_tree *wccp_tree)
806 proto_tree *list_entry_tree;
808 tl = proto_tree_add_text(wccp_tree, tvb, offset, 4 + HASH_INFO_SIZE,
809 "Web-Cache List Entry(%d)", idx);
810 list_entry_tree = proto_item_add_subtree(tl, ett_cache_info);
811 proto_tree_add_item(list_entry_tree, hf_cache_ip, tvb, offset, 4,
814 offset = dissect_hash_data(tvb, offset, list_entry_tree);
820 * takes an integer representing a "Hash Information" bitmap, and spits out
821 * the corresponding proto_tree entries, returning the next bucket number.
824 wccp_bucket_info(guint8 bucket_info, proto_tree *bucket_tree, guint32 start,
825 tvbuff_t *tvb, int offset)
829 for(i = 0; i < 8; i++) {
830 proto_tree_add_text(bucket_tree, tvb, offset, sizeof(bucket_info), "Bucket %3d: %s", start, (bucket_info & 1<<i ? "Assigned" : "Not Assigned") );
837 bucket_name(guint8 bucket)
839 if (bucket == 0xff) {
842 return wmem_strdup_printf(wmem_packet_scope(), "%u", bucket);
847 /* 5.5 WCCP Message Header */
849 dissect_wccp2_header(tvbuff_t *tvb, int offset, proto_tree *wccp_tree)
853 proto_tree_add_item(wccp_tree, hf_message_header_version, tvb, offset, 2,
856 length = tvb_get_ntohs(tvb, offset);
857 proto_tree_add_uint(wccp_tree, hf_message_header_length, tvb, offset, 2, length);
863 dissect_wccp2_info(tvbuff_t *tvb, int offset, guint16 length,
864 packet_info *pinfo, proto_tree *wccp_tree,
865 guint32 message_type)
870 proto_tree *info_tree;
872 gint (*dissector)(tvbuff_t *, int, int, packet_info *, proto_tree *);
874 /* check if all required fields are there */
875 gboolean wccp2_security_info;
876 gboolean wccp2_service_info;
877 gboolean wccp2_router_id_info;
878 gboolean wccp2_wc_id_info;
879 gboolean wccp2_rtr_view_info;
880 gboolean wccp2_wc_view_info;
881 gboolean wccp2_redirect_assignment;
882 gboolean wccp2_query_info;
883 gboolean wccp2_capabilities_info;
884 gboolean wccp2_alt_assignment;
885 gboolean wccp2_assign_map;
886 gboolean wccp2_command_extension;
887 gboolean wccp2r1_alt_assignment_map;
889 wccp2_security_info=FALSE;
890 wccp2_service_info=FALSE;
891 wccp2_router_id_info=FALSE;
892 wccp2_wc_id_info=FALSE;
893 wccp2_rtr_view_info=FALSE;
894 wccp2_wc_view_info=FALSE;
895 wccp2_redirect_assignment=FALSE;
896 wccp2_query_info=FALSE;
897 wccp2_capabilities_info=FALSE;
898 wccp2_alt_assignment=FALSE;
899 wccp2_assign_map=FALSE;
900 wccp2_command_extension=FALSE;
901 wccp2r1_alt_assignment_map=FALSE;
903 /* ugly hack: we first need to check for the address table
904 compnent, otherwise we cannot print the IP's.
906 find_wccp_address_table(tvb,offset,length,pinfo,wccp_tree);
908 while (length != 0) {
911 tf = proto_tree_add_text(wccp_tree, tvb, offset, length,
912 "Invalid WCCP Type/Length values");
914 expert_add_info_format(pinfo, tf, &ei_wccp_length_bad,
915 "The packet only has %d bytes left. That is not enough for a WCCP item type and length.",
920 type = tvb_get_ntohs(tvb, offset);
921 item_length = tvb_get_ntohs(tvb, offset+2);
924 if (item_length > tvb_length_remaining(tvb, offset)) {
925 tf = proto_tree_add_text(wccp_tree, tvb, offset, length,
926 "Excessive WCCP Length values");
927 expert_add_info_format(pinfo, tf, &ei_wccp_length_bad,
928 "The length of the item is %d but there are only %d bytes remaining in the packet, I counted %d remaining",
929 item_length, tvb_length_remaining(tvb, offset), length);
934 case WCCP2_SECURITY_INFO:
935 wccp2_security_info=TRUE;
936 ett = ett_security_info;
937 dissector = dissect_wccp2_security_info;
940 case WCCP2_SERVICE_INFO:
941 wccp2_service_info=TRUE;
942 ett = ett_service_info;
943 dissector = dissect_wccp2_service_info;
946 case WCCP2_ROUTER_ID_INFO:
947 wccp2_router_id_info=TRUE;
948 ett = ett_router_identity_info;
949 dissector = dissect_wccp2_router_identity_info;
952 case WCCP2_WC_ID_INFO:
953 wccp2_wc_id_info=TRUE;
954 ett = ett_wc_identity_info;
955 dissector = dissect_wccp2_wc_identity_info;
958 case WCCP2_RTR_VIEW_INFO:
959 wccp2_rtr_view_info=TRUE;
960 ett = ett_router_view_info;
961 dissector = dissect_wccp2_router_view_info;
964 case WCCP2_WC_VIEW_INFO:
965 wccp2_wc_view_info=TRUE;
966 ett = ett_wc_view_info;
967 dissector = dissect_wccp2_web_cache_view_info;
970 case WCCP2_REDIRECT_ASSIGNMENT:
971 wccp2_redirect_assignment=TRUE;
972 ett = ett_router_assignment_info;
973 dissector = dissect_wccp2_assignment_info;
976 case WCCP2_QUERY_INFO:
977 wccp2_query_info=TRUE;
978 ett = ett_query_info;
979 dissector = dissect_wccp2_router_query_info;
982 case WCCP2_CAPABILITIES_INFO:
983 wccp2_capabilities_info=TRUE;
984 ett = ett_capabilities_info;
985 dissector = dissect_wccp2_capability_info;
988 case WCCP2_ALT_ASSIGNMENT:
989 wccp2_alt_assignment=TRUE;
990 ett = ett_alt_assignment_info;
991 dissector = dissect_wccp2_alternate_assignment_info;
994 case WCCP2r1_ALT_ASSIGNMENT_MAP:
995 wccp2r1_alt_assignment_map=TRUE;
996 ett = ett_alt_assignment_map;
997 dissector = dissect_wccp2r1_alt_assignment_map_info;
1000 case WCCP2r1_ADDRESS_TABLE:
1001 ett = ett_address_table;
1002 dissector = dissect_wccp2r1_address_table_info;
1005 case WCCP2_ASSIGN_MAP:
1006 wccp2_assign_map=TRUE;
1007 ett = ett_assignment_map;
1008 dissector = dissect_wccp2_assignment_map;
1010 case WCCP2_COMMAND_EXTENSION:
1011 wccp2_command_extension=TRUE;
1012 ett = ett_command_extension;
1013 dissector = dissect_wccp2_command_extension;
1017 ett = ett_unknown_info;
1022 tf = proto_tree_add_text(wccp_tree, tvb, offset, item_length + 4, "%s",
1023 val_to_str(type, info_type_vals, "Unknown info type (%u)"));
1024 info_tree = proto_item_add_subtree(tf, ett);
1025 proto_tree_add_item(info_tree, hf_item_type, tvb, offset, 2, ENC_BIG_ENDIAN);
1026 proto_tree_add_item(info_tree, hf_item_length, tvb, offset+2, 2, ENC_BIG_ENDIAN);
1031 if (length < item_length) {
1032 expert_add_info_format(pinfo, tf, &ei_wccp_length_bad,
1033 "The item has length %d but the remaining WCCP data is only %d long",
1038 if (dissector != NULL) {
1039 gint remaining_item_length = (*dissector)(tvb, offset, item_length, pinfo, info_tree);
1041 /* warn if we left bytes */
1042 if (remaining_item_length > 0)
1043 expert_add_info_format(pinfo, tf, &ei_wccp_length_bad,
1044 "The dissector left %d bytes undecoded",
1045 remaining_item_length);
1047 /* error if we needed more bytes */
1048 if (remaining_item_length < 0)
1049 expert_add_info_format(pinfo, tf, &ei_wccp_length_bad,
1050 "The dissector needed %d more bytes to decode the packet, but the item is not that long",
1051 remaining_item_length);
1053 /* we assume that the item length is correct and jump forward */
1055 proto_tree_add_item(info_tree, hf_item_data, tvb, offset, item_length, ENC_NA);
1057 /* avoid looping forever */
1058 if (length < item_length)
1061 offset += item_length;
1063 /* should no happen....*/
1064 DISSECTOR_ASSERT( ( (signed int) length - item_length) >= 0);
1065 length -= item_length;
1069 /* we're done. Check if we got all the required components */
1071 switch (message_type) {
1072 case WCCP2_HERE_I_AM:
1073 if (!wccp2_security_info)
1074 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_security_info);
1075 if (!wccp2_service_info)
1076 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_service_info);
1077 if (wccp2_router_id_info)
1078 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_router_id_info);
1079 if (!wccp2_wc_id_info)
1080 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_wc_id_info);
1081 if (wccp2_rtr_view_info)
1082 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_rtr_view_info);
1083 if (!wccp2_wc_view_info)
1084 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_wc_view_info);
1085 if (wccp2_redirect_assignment)
1086 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_redirect_assignment);
1087 if (wccp2_query_info)
1088 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_query_info);
1089 if (wccp2_alt_assignment)
1090 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_alt_assignment);
1091 if (wccp2_assign_map)
1092 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_assign_map);
1093 if (wccp2r1_alt_assignment_map)
1094 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_alt_assignment_map);
1096 case WCCP2_I_SEE_YOU:
1097 if (!wccp2_security_info)
1098 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_security_info);
1099 if (!wccp2_service_info)
1100 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_service_info);
1101 if (!wccp2_router_id_info)
1102 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_router_id_info);
1103 if (wccp2_wc_id_info)
1104 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_wc_id_info);
1105 if (!wccp2_rtr_view_info)
1106 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_rtr_view_info);
1107 if (wccp2_wc_view_info)
1108 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_wc_view_info);
1109 if (wccp2_redirect_assignment)
1110 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_redirect_assignment);
1111 if (wccp2_query_info)
1112 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_query_info);
1113 if (wccp2r1_alt_assignment_map)
1114 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_alt_assignment_map);
1117 case WCCP2_REMOVAL_QUERY:
1118 if (!wccp2_security_info)
1119 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_security_info);
1120 if (!wccp2_service_info)
1121 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_service_info);
1122 if (wccp2_router_id_info)
1123 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_router_id_info);
1124 if (wccp2_wc_id_info)
1125 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_wc_id_info);
1126 if (wccp2_rtr_view_info)
1127 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_rtr_view_info);
1128 if (wccp2_wc_view_info)
1129 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_wc_view_info);
1130 if (wccp2_redirect_assignment)
1131 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_redirect_assignment);
1132 if (!wccp2_query_info)
1133 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_query_info);
1134 if (wccp2_capabilities_info)
1135 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_capabilities_info);
1136 if (wccp2_alt_assignment)
1137 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_alt_assignment);
1138 if (wccp2_assign_map)
1139 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_assign_map);
1140 if (wccp2_command_extension)
1141 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_command_extension);
1142 if (wccp2r1_alt_assignment_map)
1143 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_alt_assignment_map);
1146 case WCCP2_REDIRECT_ASSIGN:
1147 if (!wccp2_security_info)
1148 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_security_info);
1149 if (!wccp2_service_info)
1150 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_service_info);
1151 if (wccp2_router_id_info)
1152 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_router_id_info);
1153 if (wccp2_wc_id_info)
1154 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_wc_id_info);
1155 if (wccp2_rtr_view_info)
1156 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_rtr_view_info);
1157 if (wccp2_wc_view_info)
1158 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_wc_view_info);
1159 if (wccp2_query_info)
1160 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_query_info);
1161 if (wccp2_capabilities_info)
1162 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_capabilities_info);
1163 if (! (wccp2_assign_map || wccp2r1_alt_assignment_map || wccp2_alt_assignment || wccp2_redirect_assignment))
1164 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_assignment);
1165 if (wccp2_command_extension)
1166 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_command_extension);
1171 /* the following functions all need to check the length and the offset
1172 so we have a few macros to use
1175 #define EAT(x) {length -= x; offset += x;}
1177 #define EAT_AND_CHECK(x,next) {length -= x; offset += x; if (length < next) return length - next;}
1179 #define NOTE_EATEN_LENGTH(new_length) {if (new_length<0) return new_length; offset += length-new_length; length = new_length; }
1182 /* 5.1.1 Security Info Component */
1184 /* Security options */
1186 #define WCCP2_NO_SECURITY 0
1187 #define WCCP2_MD5_SECURITY 1
1189 #define SECURITY_INFO_LEN 4
1191 const value_string security_option_vals[] = {
1192 { WCCP2_NO_SECURITY, "None" },
1193 { WCCP2_MD5_SECURITY, "MD5" },
1199 dissect_wccp2_security_info(tvbuff_t *tvb, int offset, gint length,
1200 packet_info *pinfo _U_, proto_tree *info_tree)
1202 guint32 security_option;
1204 if (length < SECURITY_INFO_LEN)
1205 return (length-SECURITY_INFO_LEN);
1207 security_option = tvb_get_ntohl(tvb, offset);
1208 proto_tree_add_item(info_tree, hf_security_info_option, tvb, offset, 4, ENC_BIG_ENDIAN);
1210 if (security_option == WCCP2_MD5_SECURITY) {
1213 proto_tree_add_item(info_tree, hf_security_info_md5_checksum, tvb, offset, length-4, ENC_NA);
1221 /* 5.1.2 Service Info Component */
1223 #define SERVICE_INFO_LEN (4+4+8*2)
1225 #define WCCP2_SERVICE_STANDARD 0
1226 #define WCCP2_SERVICE_DYNAMIC 1
1228 const value_string service_type_vals[] = {
1229 { WCCP2_SERVICE_STANDARD, "Standard predefined service"},
1230 { WCCP2_SERVICE_DYNAMIC, "Dynamic CE defined service" },
1237 #define WCCP2_SI_SRC_IP_HASH 0x0001
1238 #define WCCP2_SI_DST_IP_HASH 0x0002
1239 #define WCCP2_SI_SRC_PORT_HASH 0x0004
1240 #define WCCP2_SI_DST_PORT_HASH 0x0008
1241 #define WCCP2_SI_PORTS_DEFINED 0x0010
1242 #define WCCP2_SI_PORTS_SOURCE 0x0020
1243 #define WCCP2r1_SI_REDIRECT_ONLY_PROTOCOL_0 0x0040
1244 #define WCCP2_SI_SRC_IP_ALT_HASH 0x0100
1245 #define WCCP2_SI_DST_IP_ALT_HASH 0x0200
1246 #define WCCP2_SI_SRC_PORT_ALT_HASH 0x0400
1247 #define WCCP2_SI_DST_PORT_ALT_HASH 0x0800
1251 dissect_wccp2_service_info(tvbuff_t *tvb, int offset, gint length,
1252 packet_info *pinfo, proto_tree *info_tree)
1254 guint8 service_type;
1257 proto_tree *field_tree, *ports_tree;
1260 int max_offset = offset+length;
1262 if (length != SERVICE_INFO_LEN)
1263 return length - SERVICE_INFO_LEN;
1265 service_type = tvb_get_guint8(tvb, offset);
1266 proto_tree_add_item(info_tree, hf_service_info_type, tvb,
1267 offset, 1, ENC_BIG_ENDIAN);
1269 switch (service_type) {
1271 case WCCP2_SERVICE_STANDARD:
1272 proto_tree_add_item(info_tree, hf_service_info_id_standard, tvb,
1273 offset +1 , 1, ENC_BIG_ENDIAN);
1275 tf = proto_tree_add_item(info_tree, hf_service_info_priority, tvb, offset+2, 1, ENC_BIG_ENDIAN);
1276 if (tvb_get_guint8(tvb, offset+2) != 0)
1277 expert_add_info(pinfo, tf, &ei_wccp_service_info_priority_nonzero);
1279 tf = proto_tree_add_item(info_tree, hf_service_info_protocol, tvb,
1280 offset+3, 1, ENC_BIG_ENDIAN);
1282 if (tvb_get_guint8(tvb, offset+3) != 0)
1283 expert_add_info(pinfo, tf, &ei_wccp_service_info_protocol_nonzero);
1286 case WCCP2_SERVICE_DYNAMIC:
1287 proto_tree_add_item(info_tree, hf_service_info_id_dynamic, tvb,
1288 offset +1 , 1, ENC_BIG_ENDIAN);
1289 proto_tree_add_item(info_tree, hf_service_info_priority, tvb,
1290 offset+2, 1, ENC_BIG_ENDIAN);
1291 proto_tree_add_item(info_tree, hf_service_info_protocol, tvb,
1292 offset+3, 1, ENC_BIG_ENDIAN);
1297 flags = tvb_get_ntohl(tvb, offset);
1298 tf = proto_tree_add_item(info_tree, hf_service_info_flags, tvb, offset, 4, ENC_BIG_ENDIAN);
1300 field_tree = proto_item_add_subtree(tf, ett_service_flags);
1301 proto_tree_add_item(field_tree, hf_service_info_flags_src_ip_hash, tvb, offset, 4, ENC_BIG_ENDIAN);
1302 proto_tree_add_item(field_tree, hf_service_info_flags_dest_ip_hash, tvb, offset, 4, ENC_BIG_ENDIAN);
1303 proto_tree_add_item(field_tree, hf_service_info_flags_src_port_hash, tvb, offset, 4, ENC_BIG_ENDIAN);
1304 proto_tree_add_item(field_tree, hf_service_info_flags_dest_port_hash, tvb, offset, 4, ENC_BIG_ENDIAN);
1305 proto_tree_add_item(field_tree, hf_service_info_flags_ports_defined, tvb, offset, 4, ENC_BIG_ENDIAN);
1306 /* if they are defined which ? */
1307 if (flags & WCCP2_SI_PORTS_DEFINED)
1308 proto_tree_add_item(field_tree, hf_service_info_flags_ports_source, tvb, offset, 4, ENC_BIG_ENDIAN);
1310 proto_tree_add_item(field_tree, hf_service_info_flags_redirect_only_protocol_0, tvb, offset, 4, ENC_BIG_ENDIAN);
1311 proto_tree_add_item(field_tree, hf_service_info_flags_src_ip_alt_hash, tvb, offset, 4, ENC_BIG_ENDIAN);
1312 proto_tree_add_item(field_tree, hf_service_info_flags_dest_ip_alt_hash, tvb, offset, 4, ENC_BIG_ENDIAN);
1313 proto_tree_add_item(field_tree, hf_service_info_flags_src_port_alt_hash, tvb, offset, 4, ENC_BIG_ENDIAN);
1314 proto_tree_add_item(field_tree, hf_service_info_flags_dest_port_alt_hash, tvb, offset, 4, ENC_BIG_ENDIAN);
1316 buf= (char *) wmem_alloc(wmem_packet_scope(), 128);
1317 decode_bitfield_value(buf, flags,
1318 0xFFFFFFFF ^ (WCCP2_SI_SRC_IP_HASH
1319 | WCCP2_SI_DST_IP_HASH
1320 | WCCP2_SI_SRC_PORT_HASH
1321 | WCCP2_SI_DST_PORT_HASH
1322 | WCCP2_SI_PORTS_DEFINED
1323 | WCCP2_SI_PORTS_SOURCE
1324 | WCCP2r1_SI_REDIRECT_ONLY_PROTOCOL_0
1325 | WCCP2_SI_SRC_IP_ALT_HASH
1326 | WCCP2_SI_DST_IP_ALT_HASH
1327 | WCCP2_SI_SRC_PORT_ALT_HASH
1328 | WCCP2_SI_DST_PORT_ALT_HASH),
1330 proto_tree_add_text(field_tree, tvb, offset, 2,
1332 buf, "reserved, should be 0");
1336 if (flags & WCCP2_SI_PORTS_DEFINED) {
1337 tf = proto_tree_add_text(info_tree, tvb, offset, 2*8,
1339 ports_tree = proto_item_add_subtree(tf, ett_service_info_ports);
1341 for (i = 0; i < 8; i++) {
1342 guint16 port = tvb_get_ntohs(tvb, offset);
1345 if (flags & WCCP2_SI_SRC_PORT_HASH)
1346 proto_tree_add_item(ports_tree, hf_service_info_source_port, tvb, offset, 2, ENC_BIG_ENDIAN);
1348 proto_tree_add_item(ports_tree, hf_service_info_destination_port, tvb, offset, 2, ENC_BIG_ENDIAN);
1349 proto_item_append_text(tf, " %d", port);
1352 DISSECTOR_ASSERT(offset <= max_offset);
1356 /* just use up the space if there is */
1357 if (offset + 8 * 2 <= max_offset) {
1358 proto_tree_add_text(info_tree, tvb, offset, 8*2,
1359 "Ports fields not used");
1364 return length - SERVICE_INFO_LEN;
1367 /* 6.1 Router Identity Element */
1369 dissect_wccp2_router_identity_element(tvbuff_t *tvb, int offset, packet_info *pinfo,
1375 proto_tree_add_item(tree, hf_router_identity_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1376 tf = proto_tree_add_item(tree, hf_router_identity_receive_id, tvb, offset+4, 4, ENC_BIG_ENDIAN);
1378 if (tvb_get_ntohl(tvb, offset + 4) == 0)
1379 expert_add_info(pinfo, tf, &ei_wccp_router_identity_receive_id_zero);
1382 #define ROUTER_ID_INFO_MIN_LEN (8+4+4)
1384 /* 5.3.1 Router Identity Info Component */
1386 dissect_wccp2_router_identity_info(tvbuff_t *tvb, int offset, gint length,
1387 packet_info *pinfo, proto_tree *info_tree)
1389 guint32 n_received_from;
1392 proto_tree *element_tree;
1395 return length - ROUTER_ID_INFO_MIN_LEN;
1398 te = proto_tree_add_item(info_tree, hf_router_identity_router_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1400 element_tree = proto_item_add_subtree(te,ett_wc_view_info_router_element);
1402 dissect_wccp2_router_identity_element(tvb,offset,pinfo,element_tree);
1406 proto_tree_add_item(info_tree, hf_router_identity_send_to_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1409 n_received_from = tvb_get_ntohl(tvb, offset);
1410 proto_tree_add_item(info_tree, hf_router_identity_received_from_num, tvb, offset, 4, ENC_BIG_ENDIAN);
1413 for (i = 0; i < n_received_from; i++) {
1415 return length-4*(i-n_received_from);
1418 proto_tree_add_item(info_tree, hf_router_identity_received_from_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1425 #define ROUTER_WC_ID_ELEMENT_MIN_LEN (4+2+2)
1427 /* 6.4 Web-Cache Identity Element */
1429 dissect_wccp2_web_cache_identity_element(tvbuff_t *tvb, int offset, gint length, packet_info *pinfo,
1430 proto_tree *info_tree)
1433 proto_tree *field_tree;
1435 guint data_element_type;
1438 if (length < ROUTER_WC_ID_ELEMENT_MIN_LEN)
1439 return length - ROUTER_WC_ID_ELEMENT_MIN_LEN;
1441 proto_tree_add_item(info_tree, hf_web_cache_identity_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1444 tf = proto_tree_add_item(info_tree, hf_web_cache_identity_hash_rev, tvb, offset, 2, ENC_BIG_ENDIAN);
1445 if (tvb_get_ntohs(tvb, offset) != 0)
1446 expert_add_info(pinfo, tf, &ei_wccp_web_cache_identity_hash_rev_zero);
1450 flags = tvb_get_ntohs(tvb, offset);
1451 tf = proto_tree_add_uint(info_tree, hf_web_cache_identity_flags, tvb, offset, 2, flags);
1452 data_element_type = (flags & 0x6) >> 1;
1454 field_tree = proto_item_add_subtree(tf, ett_wc_identity_flags);
1455 proto_tree_add_item(field_tree, hf_web_cache_identity_flag_hash_info, tvb, offset, 2, ENC_BIG_ENDIAN);
1456 proto_tree_add_item(field_tree, hf_web_cache_identity_flag_assign_type, tvb, offset, 2, ENC_BIG_ENDIAN);
1457 proto_tree_add_item(field_tree, hf_web_cache_identity_flag_version_request, tvb, offset, 2, ENC_BIG_ENDIAN);
1458 buf=(char *) wmem_alloc(wmem_packet_scope(), 128);
1459 decode_bitfield_value(buf, flags, 0xFFF0, 16);
1460 proto_tree_add_text(field_tree, tvb, offset, 2,
1462 buf, "reserved, should be 0");
1465 switch (data_element_type) {
1466 case WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_HASH:
1467 return dissect_wccp2_hash_assignment_data_element(tvb,offset,length,pinfo,info_tree);
1468 case WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_MASK:
1469 return dissect_wccp2_mask_assignment_data_element(tvb,offset,length,pinfo,info_tree);
1471 case WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_NOT_PRESENT:
1472 proto_tree_add_text(info_tree, tvb, offset, 2,
1473 "No Assignment Data Present");
1476 case WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_EXTENDED:
1477 return dissect_wccp2_extended_assignment_data_element(tvb,offset,length,pinfo,info_tree);
1482 /* 5.2.1 Web-Cache Identity Info Component */
1484 dissect_wccp2_wc_identity_info(tvbuff_t *tvb, int offset, gint length,
1485 packet_info *pinfo _U_, proto_tree *info_tree)
1488 proto_tree *element_tree;
1491 te = proto_tree_add_item(info_tree, hf_wc_identity_ip_address, tvb, offset, 4, ENC_BIG_ENDIAN);
1493 element_tree = proto_item_add_subtree(te, ett_wc_identity_element);
1494 return dissect_wccp2_web_cache_identity_element(tvb, offset,length, pinfo,
1498 /* 6.3 Assignment Key Element */
1500 dissect_wccp2_assignment_key_element(tvbuff_t *tvb, int offset, gint length, packet_info *pinfo _U_,
1501 proto_tree *info_tree)
1507 proto_tree_add_item(info_tree, hf_assignment_key_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1510 proto_tree_add_item(info_tree, hf_assignment_key_change_num, tvb, offset, 4, ENC_BIG_ENDIAN);
1517 #define ROUTER_VIEW_INFO_MIN_LEN (4+8+4+4)
1519 /* 5.3.2 Router View Info Component */
1521 dissect_wccp2_router_view_info(tvbuff_t *tvb, int offset, gint length,
1522 packet_info *pinfo, proto_tree *info_tree)
1525 guint32 n_web_caches;
1528 proto_tree *element_tree;
1531 if (length < ROUTER_VIEW_INFO_MIN_LEN)
1532 return length - ROUTER_VIEW_INFO_MIN_LEN;
1534 proto_tree_add_item(info_tree, hf_router_view_member_change_num, tvb, offset, 4, ENC_BIG_ENDIAN);
1537 new_length=dissect_wccp2_assignment_key_element(tvb, offset, length, pinfo, info_tree);
1538 NOTE_EATEN_LENGTH(new_length);
1540 n_routers = tvb_get_ntohl(tvb, offset);
1541 proto_tree_add_uint(info_tree, hf_router_router_num, tvb, offset, 4, n_routers);
1544 for (i = 0; i < n_routers; i++) {
1546 return length - (n_routers-i)*4 - 4;
1548 proto_tree_add_item(info_tree, hf_router_view_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1555 n_web_caches = tvb_get_ntohl(tvb, offset);
1556 proto_tree_add_uint(info_tree, hf_wc_view_wc_num, tvb, offset, 4, n_web_caches);
1559 for (i = 0; i < n_web_caches; i++) {
1561 old_length = length;
1564 return length - 4*(n_web_caches-i);
1566 te = proto_tree_add_item(info_tree, hf_router_query_info_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1568 element_tree = proto_item_add_subtree(te, ett_wc_identity_element);
1569 length = dissect_wccp2_web_cache_identity_element(tvb,
1570 offset, length, pinfo,
1575 offset += old_length - length;
1580 #define WC_VIEW_INFO_MIN_LEN (4+4+4)
1582 /* 5.2.2 Web Cache View Info Component */
1585 dissect_wccp2_web_cache_view_info(tvbuff_t *tvb, int offset, gint length,
1586 packet_info *pinfo, proto_tree *info_tree)
1589 guint32 n_web_caches;
1592 proto_tree *element_tree;
1595 if (length < WC_VIEW_INFO_MIN_LEN)
1596 return length - WC_VIEW_INFO_MIN_LEN;
1599 proto_tree_add_item(info_tree, hf_wc_view_info_change_num, tvb, offset, 4, ENC_BIG_ENDIAN);
1602 n_routers = tvb_get_ntohl(tvb, offset);
1603 proto_tree_add_uint(info_tree, hf_wc_view_router_num, tvb, offset, 4, n_routers);
1606 for (i = 0; i < n_routers; i++) {
1608 return length -8 * (n_routers-i) - 4;
1610 te = proto_tree_add_item(info_tree, hf_wc_view_info_router_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1611 /* also include the receive id in the object */
1612 proto_item_set_len(te, 8);
1614 element_tree = proto_item_add_subtree(te,ett_wc_view_info_router_element);
1615 dissect_wccp2_router_identity_element(tvb, offset, pinfo, element_tree);
1622 n_web_caches = tvb_get_ntohl(tvb, offset);
1623 proto_tree_add_uint(info_tree, hf_wc_view_wc_num, tvb, offset, 4, n_web_caches);
1626 for (i = 0; i < n_web_caches; i++) {
1628 return length - 4*(n_web_caches-i);
1630 proto_tree_add_item(info_tree, hf_wc_view_info_wc_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1636 /* 6.2 Router Assignment Element */
1638 dissect_wccp2_router_assignment_element(tvbuff_t *tvb, int offset,
1639 gint length, packet_info *pinfo, proto_tree *info_tree)
1641 dissect_wccp2_router_identity_element(tvb,offset,pinfo,info_tree);
1643 proto_tree_add_item(info_tree, hf_router_assignment_element_change_num, tvb, offset, 4, ENC_BIG_ENDIAN);
1647 static const gchar *
1648 assignment_bucket_name(guint8 bucket)
1652 if (bucket == 0xff) {
1655 cur=wmem_strdup_printf(wmem_packet_scope(), "%u%s", bucket & 0x7F,
1656 (bucket & 0x80) ? " (Alt)" : "");
1661 #define ASSIGNMENT_INFO_MIN_LEN (8+4+4)
1663 /* 5.4.1 Assignment Info Component */
1665 dissect_wccp2_assignment_info(tvbuff_t *tvb, int offset, gint length,
1666 packet_info *pinfo, proto_tree *info_tree)
1671 proto_tree *element_tree;
1674 if (length < ASSIGNMENT_INFO_MIN_LEN)
1675 return length - ASSIGNMENT_INFO_MIN_LEN;
1678 new_length=dissect_wccp2_assignment_key_element(tvb, offset, length, pinfo, info_tree);
1679 NOTE_EATEN_LENGTH(new_length);
1681 n_routers = tvb_get_ntohl(tvb, offset);
1682 proto_tree_add_uint(info_tree, hf_assignment_info_router_num, tvb, offset, 4, n_routers);
1685 for (i = 0; i < n_routers; i++) {
1687 return length - 12*(n_routers-i)-4-256;
1689 te = proto_tree_add_item(info_tree, hf_assignment_info_router_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1691 element_tree = proto_item_add_subtree(te, ett_router_assignment_element);
1692 dissect_wccp2_router_assignment_element(tvb, offset, length , pinfo,
1697 new_length = dissect_wccp2_hash_buckets_assignment_element(tvb, offset, length, pinfo, info_tree);
1698 NOTE_EATEN_LENGTH(new_length);
1703 #define QUERY_INFO_LEN (4+4+4+4)
1705 /* 5.5.1 Router Query Info Component */
1707 dissect_wccp2_router_query_info(tvbuff_t *tvb, int offset, gint length,
1708 packet_info *pinfo, proto_tree *info_tree)
1710 if (length < QUERY_INFO_LEN)
1711 return length - QUERY_INFO_LEN;
1713 dissect_wccp2_router_identity_element(tvb,offset,pinfo,info_tree);
1716 proto_tree_add_item(info_tree, hf_router_query_info_send_to_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1718 proto_tree_add_item(info_tree, hf_router_query_info_target_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1724 /* 6.5 Hash Buckets Assignment Element */
1725 static gint dissect_wccp2_hash_buckets_assignment_element(tvbuff_t *tvb, int offset, gint length,
1726 packet_info *pinfo _U_, proto_tree *info_tree)
1728 guint32 i,n_web_caches;
1730 proto_tree *element_tree;
1735 n_web_caches = tvb_get_ntohl(tvb, offset);
1736 te = proto_tree_add_uint(info_tree, hf_hash_buckets_assignment_wc_num, tvb, offset, 4, n_web_caches);
1739 element_tree = proto_item_add_subtree(te,ett_hash_buckets_assignment_wc_element);
1740 for (i = 0; i < n_web_caches; i++) {
1744 return length - 4*(n_web_caches-i)-256;
1746 l_te = proto_tree_add_item(element_tree, hf_hash_buckets_assignment_wc_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1748 proto_item_append_text(l_te, " id: %d", i);
1752 te = proto_tree_add_text(info_tree,tvb, offset,256, "Buckets");
1753 element_tree = proto_item_add_subtree(te,ett_hash_buckets_assignment_buckets);
1755 for (i = 0; i < 256; i += 4) {
1757 return length - (256-i);
1759 proto_tree_add_text(element_tree, tvb, offset, 4,
1760 "Buckets %3d - %3d: %10s %10s %10s %10s",
1762 assignment_bucket_name(tvb_get_guint8(tvb, offset)),
1763 assignment_bucket_name(tvb_get_guint8(tvb, offset+1)),
1764 assignment_bucket_name(tvb_get_guint8(tvb, offset+2)),
1765 assignment_bucket_name(tvb_get_guint8(tvb, offset+3)));
1771 #define WCCP2_FORWARDING_METHOD_GRE 0x00000001
1772 #define WCCP2_FORWARDING_METHOD_L2 0x00000002
1774 static const capability_flag forwarding_method_flags[] = {
1775 { WCCP2_FORWARDING_METHOD_GRE, "IP-GRE", &hf_capability_forwarding_method_flag_gre },
1776 { WCCP2_FORWARDING_METHOD_L2, "L2", &hf_capability_forwarding_method_flag_l2 },
1780 #define WCCP2_ASSIGNMENT_METHOD_HASH 0x00000001
1781 #define WCCP2_ASSIGNMENT_METHOD_MASK 0x00000002
1783 static const capability_flag assignment_method_flags[] = {
1784 { WCCP2_ASSIGNMENT_METHOD_HASH, "Hash", &hf_capability_assignment_method_flag_hash },
1785 { WCCP2_ASSIGNMENT_METHOD_MASK, "Mask", &hf_capability_assignment_method_flag_mask },
1790 #define WCCP2_PACKET_RETURN_METHOD_GRE 0x00000001
1791 #define WCCP2_PACKET_RETURN_METHOD_L2 0x00000002
1793 static const capability_flag packet_return_method_flags[] = {
1794 { WCCP2_PACKET_RETURN_METHOD_GRE, "IP-GRE", &hf_capability_return_method_flag_gre },
1795 { WCCP2_PACKET_RETURN_METHOD_L2, "L2", &hf_capability_return_method_flag_l2 },
1799 #define WCCP2_COMMAND_TYPE_SHUTDOWN 1
1800 #define WCCP2_COMMAND_TYPE_SHUTDOWN_RESPONSE 2
1802 static const value_string wccp_command_type_vals[] = {
1803 { WCCP2_COMMAND_TYPE_SHUTDOWN, "CE shutting down" },
1804 { WCCP2_COMMAND_TYPE_SHUTDOWN_RESPONSE, "Router Acknowledge CE shutdown"},
1810 /* 5.1.3 Capabilities Info Component */
1813 dissect_wccp2_capability_info(tvbuff_t *tvb, int offset, gint length,
1814 packet_info *pinfo, proto_tree *info_tree)
1816 gint capability_length;
1818 while (length >= 8) {
1819 capability_length = dissect_wccp2_capability_element(tvb,offset,length,pinfo,info_tree);
1821 NOTE_EATEN_LENGTH(capability_length);
1827 #define ALT_COMMAND_EXTENSION_MIN_LEN (4)
1829 /* 5.1.4 && 6.12 Command Extension Component */
1832 dissect_wccp2_command_extension(tvbuff_t *tvb, int offset,
1833 int length, packet_info *pinfo _U_, proto_tree *info_tree)
1835 guint16 command_type;
1836 guint16 command_length;
1842 if (length < ALT_COMMAND_EXTENSION_MIN_LEN )
1843 return length - ALT_COMMAND_EXTENSION_MIN_LEN ;
1845 command_type = tvb_get_ntohs(tvb, offset);
1846 proto_tree_add_item(info_tree, hf_command_element_type, tvb, offset, 2, ENC_BIG_ENDIAN);
1850 command_length = tvb_get_ntohs(tvb, offset);
1851 proto_tree_add_item(info_tree, hf_command_element_length, tvb, offset, 2, ENC_BIG_ENDIAN);
1852 proto_tree_add_text(info_tree, tvb, offset, 2,
1853 "Command length: %u", command_length);
1856 if (((command_type == WCCP2_COMMAND_TYPE_SHUTDOWN) ||
1857 (command_type == WCCP2_COMMAND_TYPE_SHUTDOWN_RESPONSE)) &&
1858 (command_length == 4)) {
1861 proto_tree_add_item(info_tree, hf_command_element_shutdown_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1863 if (length < command_length)
1864 return length - command_length;
1866 proto_tree_add_text(info_tree, tvb, offset, command_length,
1869 EAT(command_length);
1874 /* 5.1.5 Address Table Component */
1875 /* this function is special as it can be invoked twice during a packet decode:
1876 once to get the tables, once to display them
1879 dissect_wccp2r1_address_table_info(tvbuff_t *tvb, int offset,
1880 int length, packet_info *pinfo, proto_tree *info_tree)
1882 guint16 address_length;
1884 proto_tree *element_tree=NULL;
1885 proto_item *tf=NULL;
1887 wccp_wccp_address_table.in_use = TRUE;
1890 tf = proto_tree_get_parent(info_tree);
1893 return length - 2*4;
1896 wccp_wccp_address_table.family = tvb_get_ntohs(tvb,offset);
1897 if (pinfo && info_tree)
1898 proto_tree_add_item(info_tree, hf_address_table_family, tvb,
1899 offset, 2, ENC_BIG_ENDIAN);
1902 address_length = tvb_get_ntohs(tvb,offset);
1904 proto_tree_add_item(info_tree, hf_address_table_address_length, tvb, offset, 2, ENC_BIG_ENDIAN);
1907 wccp_wccp_address_table.table_length = tvb_get_ntohl(tvb,offset);
1908 if (pinfo && info_tree) {
1909 tf = proto_tree_add_item(info_tree, hf_address_table_length, tvb, offset, 4, ENC_BIG_ENDIAN);
1910 element_tree = proto_item_add_subtree(tf, ett_table_element);
1914 /* check if the length is valid and allocate the tables if needed*/
1915 switch (wccp_wccp_address_table.family) {
1917 if (wccp_wccp_address_table.table_ipv4 == NULL)
1918 wccp_wccp_address_table.table_ipv4 = (guint32 *)
1919 wmem_alloc(wmem_packet_scope(), wccp_wccp_address_table.table_length * 4);
1920 if ((address_length != 4) && (pinfo && info_tree)) {
1921 expert_add_info_format(pinfo, tf, &ei_wccp_length_bad,
1922 "The Address length must be 4, but I found %d for IPv4 addresses. Correcting this.",
1928 if (wccp_wccp_address_table.table_ipv6 == NULL)
1929 wccp_wccp_address_table.table_ipv6 = (struct e_in6_addr *)
1930 wmem_alloc(wmem_packet_scope(), wccp_wccp_address_table.table_length * sizeof(struct e_in6_addr));
1931 if ((address_length != 16) && (pinfo && info_tree)) {
1932 expert_add_info_format(pinfo, tf, &ei_wccp_length_bad,
1933 "The Address length must be 16, but I found %d for IPv6 addresses. Correcting this",
1939 if (pinfo && info_tree) {
1940 expert_add_info_format(pinfo, tf, &ei_wccp_address_table_family_unknown,
1941 "Unknown address family: %d", wccp_wccp_address_table.family);
1945 /* now read the addresses and print/store them */
1947 for(i=0; i<wccp_wccp_address_table.table_length; i++) {
1950 /* do we have space? */
1951 if (length < address_length) {
1953 expert_add_info_format(pinfo, tf, &ei_wccp_length_bad, "Ran out of space to decode");
1955 /* first clean up: */
1956 wccp_wccp_address_table.in_use = FALSE;
1957 wccp_wccp_address_table.family = -1;
1958 wccp_wccp_address_table.version = -1;
1959 wccp_wccp_address_table.table_length = 0;
1960 wccp_wccp_address_table.table_ipv4 = (guint32 *) NULL;
1961 wccp_wccp_address_table.table_ipv6 = (struct e_in6_addr *)NULL;
1963 /* ABORT The decode */
1964 return length - address_length;
1967 switch (wccp_wccp_address_table.family) {
1970 addr = tvb_ip_to_str(tvb, offset);
1971 if (wccp_wccp_address_table.table_ipv4 != NULL)
1972 wccp_wccp_address_table.table_ipv4[i] = tvb_get_ntohl(tvb,offset);
1976 addr = tvb_ip6_to_str(tvb,offset);
1977 if (wccp_wccp_address_table.table_ipv6 != NULL)
1978 tvb_get_ipv6(tvb, offset, &(wccp_wccp_address_table.table_ipv6[i]));
1981 addr = wmem_strdup_printf(wmem_packet_scope(), "unknown family");
1985 proto_tree_add_string_format_value(element_tree, hf_address_table_element, tvb,
1986 offset, address_length, addr,
1987 "%d: %s", i+1, addr);
1989 EAT(address_length);
1998 #define HASH_ASSIGNMENT_INFO_MIN_LEN (4+256)
2000 /* part of 5.6.11 Alternate Assignment Component */
2002 dissect_wccp2_hash_assignment_info(tvbuff_t *tvb, int offset, gint length,
2003 packet_info *pinfo, proto_tree *info_tree)
2005 guint32 n_web_caches;
2008 if (length < HASH_ASSIGNMENT_INFO_MIN_LEN)
2009 return length - ASSIGNMENT_INFO_MIN_LEN;
2011 n_web_caches = tvb_get_ntohl(tvb, offset);
2012 proto_tree_add_uint(info_tree, hf_wc_view_wc_num, tvb, offset, 4, n_web_caches);
2015 for (i = 0; i < n_web_caches; i++) {
2017 return length - 4*(n_web_caches-i)-256;
2019 proto_tree_add_text(info_tree, tvb, offset, 4,
2020 "Web-Cache %d: IP address %s", i,
2021 decode_wccp_encoded_address(tvb, offset, pinfo, info_tree));
2025 for (i = 0; i < 256; i += 4) {
2027 return length - (256-i);
2029 proto_tree_add_text(info_tree, tvb, offset, 4,
2030 "Buckets %d - %d: %10s %10s %10s %10s",
2032 assignment_bucket_name(tvb_get_guint8(tvb, offset)),
2033 assignment_bucket_name(tvb_get_guint8(tvb, offset+1)),
2034 assignment_bucket_name(tvb_get_guint8(tvb, offset+2)),
2035 assignment_bucket_name(tvb_get_guint8(tvb, offset+3)));
2041 /* 5.3.3 Assignment Map Component */
2042 static gint dissect_wccp2_assignment_map(tvbuff_t *tvb, int offset,
2043 int length, packet_info *pinfo, proto_tree *info_tree)
2047 new_length=dissect_wccp2_mask_value_set_list(tvb, offset, length, pinfo, info_tree);
2049 NOTE_EATEN_LENGTH(new_length);
2056 #define ALT_ASSIGNMENT_MAP_MIN_LEN (4)
2058 /* 5.3.4 Alternate Assignment Map Component */
2060 dissect_wccp2r1_alt_assignment_map_info(tvbuff_t *tvb, int offset,
2061 int length, packet_info *pinfo, proto_tree *info_tree)
2063 guint16 assignment_type;
2064 guint16 assignment_length;
2065 proto_item *tf=NULL;
2067 if (length < ALT_ASSIGNMENT_MAP_MIN_LEN )
2068 return length - ALT_ASSIGNMENT_MAP_MIN_LEN ;
2071 assignment_type = tvb_get_ntohs(tvb, offset);
2072 proto_tree_add_item(info_tree, hf_alt_assignment_map_assignment_type, tvb, offset, 2, ENC_BIG_ENDIAN);
2075 assignment_length = tvb_get_ntohs(tvb, offset);
2076 tf=proto_tree_add_item(info_tree, hf_alt_assignment_map_assignment_length, tvb, offset, 2, ENC_BIG_ENDIAN);
2079 if (length < assignment_length)
2080 expert_add_info_format(pinfo, tf, &ei_wccp_assignment_length_bad,
2081 "Assignment length is %d but only %d remain in the packet. Ignoring this for now",
2082 assignment_length, length);
2084 if (length > assignment_length) {
2085 expert_add_info_format(pinfo, tf, &ei_wccp_assignment_length_bad,
2086 "Assignment length is %d but %d remain in the packet. Assuming that the assignment length is wrong and setting it to %d.",
2087 assignment_length, length, length);
2088 assignment_length = length;
2091 switch (assignment_type) {
2092 case WCCP2_HASH_ASSIGNMENT_TYPE:
2093 return dissect_wccp2_assignment_info(tvb, offset, assignment_length,
2095 case WCCP2_MASK_ASSIGNMENT_TYPE:
2096 return dissect_wccp2_mask_value_set_list(tvb, offset, assignment_length,
2098 case WCCP2r1_ALT_MASK_ASSIGNMENT_TYPE:
2099 return dissect_wccp2_alternate_mask_value_set_list(tvb, offset, assignment_length,
2110 /* 6.6 Hash Assignment Data Element */
2112 dissect_wccp2_hash_assignment_data_element(tvbuff_t *tvb, int offset, gint length,
2113 packet_info *pinfo _U_,
2114 proto_tree *info_tree)
2117 proto_item *bucket_item;
2118 proto_tree *bucket_tree;
2124 bucket_item = proto_tree_add_text(info_tree, tvb, offset, 8*4,
2125 "Hash Assignment Data");
2126 bucket_tree = proto_item_add_subtree(bucket_item, ett_hash_assignment_buckets);
2128 for (i = 0, n = 0; i < 32; i++) {
2133 bucket_info = tvb_get_guint8(tvb, offset);
2134 n = wccp_bucket_info(bucket_info, bucket_tree, n, tvb, offset);
2142 return dissect_wccp2_assignment_weight_and_status_element(tvb, offset, length, pinfo, info_tree);
2145 /* 6.7 Mask Assignment Data Element */
2147 dissect_wccp2_mask_assignment_data_element(tvbuff_t *tvb, int offset, gint length, packet_info *pinfo,
2148 proto_tree *info_tree)
2151 proto_item *mask_item;
2152 proto_tree *mask_tree;
2153 gint new_length,start;
2156 mask_item = proto_tree_add_text(info_tree, tvb, offset, 4,
2157 "Mask Assignment Data");
2158 mask_tree = proto_item_add_subtree(mask_item, ett_mask_assignment_data_element);
2161 new_length=dissect_wccp2_mask_value_set_list(tvb, offset, length, pinfo, mask_tree);
2163 NOTE_EATEN_LENGTH(new_length);
2168 new_length = dissect_wccp2_assignment_weight_and_status_element(tvb, offset, length, pinfo, info_tree);
2169 NOTE_EATEN_LENGTH(new_length);
2171 proto_item_set_len(mask_item, offset-start);
2176 /* 5.7.5 Alternate Mask Assignment Data Element */
2178 dissect_wccp2_alternate_mask_assignment_data_element(tvbuff_t *tvb, int offset, gint length, packet_info *pinfo,
2179 proto_tree *info_tree)
2181 proto_item *mask_item;
2182 proto_tree *mask_tree;
2184 mask_item = proto_tree_add_text(info_tree, tvb, offset, length,
2185 "Alternate Mask Assignment Data");
2186 mask_tree = proto_item_add_subtree(mask_item, ett_alternate_mask_assignment_data_element);
2196 new_length=dissect_wccp2_alternate_mask_value_set_list(tvb, offset, length, pinfo, mask_tree);
2198 NOTE_EATEN_LENGTH(new_length);
2204 return dissect_wccp2_assignment_weight_and_status_element(tvb, offset, length, pinfo, info_tree);
2208 /* 6.9 Assignment Weight and Status Data Element */
2210 dissect_wccp2_assignment_weight_and_status_element(tvbuff_t *tvb, int offset, gint length,
2211 packet_info *pinfo _U_,
2212 proto_tree *info_tree)
2219 proto_tree_add_item(info_tree, hf_assignment_weight, tvb, offset, 2, ENC_BIG_ENDIAN);
2221 proto_tree_add_item(info_tree, hf_assignment_status, tvb, offset, 2, ENC_BIG_ENDIAN);
2227 /* 6.10 Extended Assignment Data Element */
2229 dissect_wccp2_extended_assignment_data_element(tvbuff_t *tvb, int offset, gint length, packet_info *pinfo,
2230 proto_tree *info_tree)
2232 proto_item *element_item, *header;
2233 proto_tree *item_tree;
2235 guint type_of_assignment;
2237 gint assignment_length;
2243 header = proto_tree_add_text(info_tree, tvb, offset, length,
2244 "Extended Assignment Data Element");
2246 item_tree = proto_item_add_subtree(header, ett_extended_assigment_data_element);
2248 type_of_assignment = tvb_get_ntohs(tvb, offset);
2249 proto_tree_add_item(item_tree, hf_extended_assignment_data_type, tvb, offset, 2, ENC_BIG_ENDIAN);
2252 assignment_length = tvb_get_ntohs(tvb,offset);
2253 element_item = proto_tree_add_item(item_tree, hf_extended_assignment_data_length, tvb, offset, 2, ENC_BIG_ENDIAN);
2256 if (length < assignment_length)
2257 expert_add_info_format(pinfo, element_item, &ei_wccp_assignment_length_bad,
2258 "Assignment length is %d but only %d remain in the packet. Ignoring this for now",
2259 assignment_length, length);
2261 /* Now a common bug seems to be to set the assignment_length to the length -4
2263 if ((length > assignment_length) &&
2264 (length == (assignment_length + 4)))
2266 expert_add_info_format(pinfo, element_item, &ei_wccp_assignment_length_bad,
2267 "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",
2268 assignment_length, length, length);
2269 assignment_length = length;
2273 proto_item_set_len(header, assignment_length+4);
2275 switch (type_of_assignment)
2277 case WCCP2_HASH_ASSIGNMENT_TYPE:
2278 return dissect_wccp2_hash_assignment_data_element(tvb, offset, assignment_length,
2280 case WCCP2_MASK_ASSIGNMENT_TYPE:
2281 return dissect_wccp2_mask_assignment_data_element(tvb, offset, assignment_length,
2283 case WCCP2r1_ALT_MASK_ASSIGNMENT_TYPE:
2284 return dissect_wccp2_alternate_mask_assignment_data_element(tvb, offset, assignment_length,
2286 case WCCP2r1_ASSIGNMENT_WEIGHT_STATUS:
2287 return dissect_wccp2_assignment_weight_and_status_element(tvb, offset, assignment_length,
2298 /* 6.11 Capability Element */
2300 dissect_wccp2_capability_element(tvbuff_t *tvb, int offset, gint length,
2301 packet_info *pinfo, proto_tree *info_tree)
2303 guint16 capability_type;
2304 guint16 capability_val_len;
2305 proto_item *te, *header, *tf;
2306 proto_tree *element_tree;
2312 capability_type = tvb_get_ntohs(tvb, offset);
2313 capability_val_len = tvb_get_ntohs(tvb, offset + 2);
2314 header = te = proto_tree_add_item(info_tree, hf_capability_element_type, tvb, offset, 2, ENC_BIG_ENDIAN);
2316 proto_item_set_len(te, capability_val_len + 4);
2317 element_tree = proto_item_add_subtree(te, ett_capability_element);
2319 tf = proto_tree_add_uint(element_tree, hf_capability_element_length, tvb, offset+2, 2, capability_val_len);
2321 proto_tree_add_text(element_tree, tvb, offset, 2,
2323 val_to_str(capability_type,
2324 capability_type_vals, "Unknown (0x%08X)"));
2325 if (capability_val_len < 4) {
2326 expert_add_info_format(pinfo, tf, &ei_wccp_capability_element_length,
2327 "Value Length: %u (illegal, must be >= 4)", capability_val_len);
2331 if (length < (4+capability_val_len))
2332 return length - 4 - capability_val_len;
2334 switch (capability_type) {
2335 case WCCP2_FORWARDING_METHOD:
2336 dissect_32_bit_capability_flags(tvb, offset,
2338 ett_capability_forwarding_method,
2339 forwarding_method_flags, element_tree, header);
2342 case WCCP2_ASSIGNMENT_METHOD:
2343 dissect_32_bit_capability_flags(tvb, offset,
2345 ett_capability_assignment_method,
2346 assignment_method_flags, element_tree, header);
2349 case WCCP2_PACKET_RETURN_METHOD:
2350 dissect_32_bit_capability_flags(tvb, offset,
2352 ett_capability_return_method,
2353 packet_return_method_flags, element_tree, header);
2356 case WCCP2_TRANSMIT_T:
2357 dissect_transmit_t_capability(tvb, te, offset,
2359 ett_capability_transmit_t,element_tree);
2362 case WCCP2_TIMER_SCALE:
2363 dissect_timer_scale_capability(tvb, offset,
2365 ett_capability_timer_scale, element_tree);
2368 proto_tree_add_text(element_tree, tvb,
2369 offset, capability_val_len,
2371 tvb_bytes_to_ep_str(tvb, offset,
2372 capability_val_len));
2375 return length - 4 - capability_val_len;
2379 /* 6.13 Mask/Value Set List */
2381 dissect_wccp2_mask_value_set_list(tvbuff_t *tvb, int offset,
2382 int length, packet_info *pinfo, proto_tree *info_tree)
2387 proto_tree *element_tree;
2394 te = proto_tree_add_text(info_tree, tvb, offset, 4, "Mask/Value Set List");
2395 element_tree = proto_item_add_subtree(te, ett_mv_set_list);
2399 num_of_elem = tvb_get_ntohl(tvb, offset);
2400 proto_tree_add_item(element_tree, hf_mask_value_set_list_num_elements,
2401 tvb, offset, 4, ENC_BIG_ENDIAN);
2402 /* proto_tree_add_uint(element_tree, , tvb, offset, 4, num_of_elem); */
2405 for (i = 0; i < num_of_elem; i++)
2409 new_length=dissect_wccp2_mask_value_set_element(tvb, offset, length, i, pinfo, element_tree);
2411 NOTE_EATEN_LENGTH(new_length);
2414 proto_item_set_len(te, offset-start);
2422 /* 6.15 Mask Element */
2424 dissect_wccp2_mask_element(tvbuff_t *tvb, int offset, gint length, packet_info *pinfo _U_, proto_tree *info_tree)
2429 proto_tree_add_item(info_tree, hf_mask_element_src_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
2431 proto_tree_add_item(info_tree, hf_mask_element_dest_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
2434 proto_tree_add_item(info_tree, hf_mask_element_src_port, tvb, offset, 2, ENC_BIG_ENDIAN);
2436 proto_tree_add_item(info_tree, hf_mask_element_dest_port, tvb, offset, 2, ENC_BIG_ENDIAN);
2447 /* 6.17 Alternate Mask/Value Set List */
2448 static gint dissect_wccp2_alternate_mask_value_set_list(tvbuff_t *tvb, int offset,
2449 int length, packet_info *pinfo, proto_tree *info_tree)
2452 proto_tree *list_tree;
2453 guint num_of_val_elements;
2459 header = proto_tree_add_text(info_tree, tvb, offset, length,
2460 "Alternate Mask/Value Set List");
2461 list_tree = proto_item_add_subtree(header, ett_alternate_mask_value_set);
2463 num_of_val_elements = tvb_get_ntohl(tvb, offset);
2464 proto_tree_add_uint(list_tree, hf_alt_assignment_mask_value_set_list_num_elements, tvb, offset, 4, num_of_val_elements);
2467 for(i=0;i<num_of_val_elements;i++) {
2470 new_length=dissect_wccp2_alternate_mask_value_set_element(tvb, offset, length, i, pinfo, list_tree);
2472 NOTE_EATEN_LENGTH(new_length);
2478 /* 6.18 Alternate Mask/Value Set Element */
2480 dissect_wccp2_alternate_mask_value_set_element(tvbuff_t *tvb, int offset, gint length, guint el_index, packet_info *pinfo, proto_tree *info_tree)
2482 proto_item *tl, *header;
2483 proto_tree *element_tree, *value_tree;
2484 guint number_of_elements;
2485 gint new_length, total_length;
2488 header = proto_tree_add_text(info_tree, tvb, offset, 0,
2489 "Alternate Mask/Value Set Element(%d)", el_index);
2490 element_tree = proto_item_add_subtree(header, ett_alternate_mask_value_set_element);
2494 new_length=dissect_wccp2_mask_element(tvb,offset,length,pinfo,element_tree);
2495 total_length += length - new_length;
2496 NOTE_EATEN_LENGTH(new_length);
2501 number_of_elements = tvb_get_ntohl(tvb, offset);
2502 tl = proto_tree_add_uint(element_tree, hf_alt_assignment_mask_value_set_element_num_wc_value_elements, tvb, offset, 4, number_of_elements);
2503 value_tree = proto_item_add_subtree(tl, ett_alternate_mv_set_element_list);
2507 for (i=0; i < number_of_elements; i++) {
2508 new_length=dissect_wccp2_web_cache_value_element(tvb, offset, length, pinfo, value_tree);
2509 total_length += length - new_length;
2510 NOTE_EATEN_LENGTH(new_length);
2512 proto_item_set_len(header, total_length);
2517 /* 6.19 Web-Cache Value Element */
2519 dissect_wccp2_web_cache_value_element(tvbuff_t *tvb, int offset, gint length, packet_info *pinfo _U_, proto_tree *info_tree)
2521 guint number_of_elements;
2523 proto_tree *element_tree;
2529 tl = proto_tree_add_item(info_tree, hf_web_cache_value_element_wc_address, tvb, offset, 4, ENC_BIG_ENDIAN);
2531 element_tree = proto_item_add_subtree(tl, ett_web_cache_value_element_list);
2534 number_of_elements = tvb_get_ntohl(tvb, offset);
2535 proto_tree_add_uint(element_tree, hf_web_cache_value_element_num_values, tvb, offset, 4, number_of_elements);
2538 for (i=0; i < number_of_elements; i++) {
2540 return length - 4*(number_of_elements-i);
2542 proto_tree_add_text(element_tree, tvb, offset, 4,
2543 "Value Sequence Number %d: %x",
2545 tvb_get_ntohl(tvb, offset));
2553 /* End of standard functions */
2557 dissect_32_bit_capability_flags(tvbuff_t *tvb, int curr_offset,
2558 guint16 capability_val_len, gint ett, const capability_flag *flags,
2559 proto_tree *element_tree, proto_item *header)
2561 guint32 capability_val;
2563 proto_tree *method_tree;
2565 gboolean first = TRUE;
2567 capability_val = tvb_get_ntohl(tvb, curr_offset + 4);
2568 tm = proto_tree_add_uint(element_tree, hf_capability_info_value, tvb, curr_offset + 4, 4, capability_val);
2570 DISSECTOR_ASSERT(capability_val_len == 4);
2572 for (i = 0; flags[i].short_name != NULL; i++) {
2573 if (capability_val & flags[i].value) {
2575 proto_item_append_text( tm, " (%s", flags[i].short_name);
2576 proto_item_append_text( header, " (%s", flags[i].short_name);
2579 proto_item_append_text( tm, ", %s", flags[i].short_name);
2580 proto_item_append_text( header, " (%s", flags[i].short_name);
2585 if (first == FALSE) {
2586 proto_item_append_text( tm, ")");
2587 proto_item_append_text( header, ")");
2590 method_tree = proto_item_add_subtree(tm, ett);
2591 for (i = 0; flags[i].phf != NULL; i++)
2592 proto_tree_add_item(method_tree, *(flags[i].phf), tvb, curr_offset+4, 4, ENC_BIG_ENDIAN);
2597 /* 6.11.4 Capability Type WCCP2_TRANSMIT_T */
2599 dissect_transmit_t_capability(tvbuff_t *tvb, proto_item *te, int curr_offset,
2600 guint16 capability_val_len, gint ett, proto_tree *element_tree)
2602 guint16 upper_limit, lower_limit;
2604 proto_tree *method_tree;
2606 DISSECTOR_ASSERT(capability_val_len == 4);
2608 upper_limit = tvb_get_ntohs(tvb, curr_offset);
2609 lower_limit = tvb_get_ntohs(tvb, curr_offset + 2);
2611 if ( upper_limit == 0) {
2612 tm = proto_tree_add_text(element_tree, tvb, curr_offset, 2,
2613 "Only accepting one value");
2614 method_tree = proto_item_add_subtree(tm, ett);
2615 proto_tree_add_text(method_tree, tvb, curr_offset, 2,
2616 "Reserved, must be 0: %d", upper_limit);
2618 proto_tree_add_item(method_tree, hf_capability_transmit_t , tvb, curr_offset+2, 2, ENC_BIG_ENDIAN);
2619 proto_item_append_text(te, " %d ms", lower_limit);
2621 tm = proto_tree_add_text(element_tree, tvb, curr_offset, 2,
2622 "Accepting a range");
2623 method_tree = proto_item_add_subtree(tm, ett);
2624 proto_tree_add_item(method_tree, hf_capability_transmit_t_upper_limit,
2625 tvb, curr_offset, 2, ENC_BIG_ENDIAN);
2627 proto_tree_add_item(method_tree, hf_capability_transmit_t_lower_limit,
2628 tvb, curr_offset+2, 2, ENC_BIG_ENDIAN);
2629 proto_item_append_text(te, " < %d ms > %d ms", lower_limit, upper_limit);
2635 dissect_timer_scale_capability(tvbuff_t *tvb, int curr_offset,
2636 guint16 capability_val_len, gint ett, proto_tree *element_tree)
2640 proto_tree *method_tree;
2642 DISSECTOR_ASSERT(capability_val_len == 4);
2644 a = tvb_get_guint8(tvb, curr_offset);
2645 c = tvb_get_guint8(tvb, curr_offset+2);
2649 tm = proto_tree_add_text(element_tree, tvb, curr_offset, 2,
2650 "Only accepting one value");
2652 method_tree = proto_item_add_subtree(tm, ett);
2653 proto_tree_add_text(method_tree, tvb, curr_offset, 1,
2654 "Reserved, must be 0: %d", a);
2656 proto_tree_add_item(method_tree, hf_capability_timer_scale_timeout_scale,
2657 tvb, curr_offset+1, 1, ENC_BIG_ENDIAN);
2658 proto_tree_add_text(method_tree, tvb, curr_offset+2, 1,
2659 "Reserved, must be 0: %d", c);
2660 proto_tree_add_item(method_tree, hf_capability_timer_scale_ra_timer_scale,
2661 tvb, curr_offset+3, 1, ENC_BIG_ENDIAN);
2663 proto_tree_add_text(element_tree, tvb, curr_offset, 1,
2664 "Error A is 0, but C is not");
2668 proto_tree_add_text(element_tree, tvb, curr_offset, 1,
2669 "Error C is 0, but A is not");
2671 tm = proto_tree_add_text(element_tree, tvb, curr_offset, 2,
2672 "Accepting a range");
2673 method_tree = proto_item_add_subtree(tm, ett);
2674 proto_tree_add_item(method_tree, hf_capability_timer_scale_timeout_scale_upper_limit,
2675 tvb, curr_offset, 1, ENC_BIG_ENDIAN);
2677 proto_tree_add_item(method_tree, hf_capability_timer_scale_timeout_scale_lower_limit,
2678 tvb, curr_offset+1, 1, ENC_BIG_ENDIAN);
2679 proto_tree_add_item(method_tree, hf_capability_timer_scale_ra_scale_upper_limit,
2680 tvb, curr_offset+2, 1, ENC_BIG_ENDIAN);
2681 proto_tree_add_item(method_tree, hf_capability_timer_scale_ra_scale_lower_limit,
2682 tvb, curr_offset+3, 1, ENC_BIG_ENDIAN);
2688 /* 6.16 Value Element */
2690 dissect_wccp2_value_element(tvbuff_t *tvb, int offset, gint length, int idx, packet_info *pinfo, proto_tree *info_tree)
2693 proto_tree *element_tree;
2698 tl = proto_tree_add_text(info_tree, tvb, offset, 16, "Value Element(%u) %s",
2699 idx,decode_wccp_encoded_address(tvb, offset+4+4+2+2, pinfo, info_tree));
2700 element_tree = proto_item_add_subtree(tl, ett_value_element);
2702 proto_tree_add_item(element_tree, hf_value_element_src_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
2704 proto_tree_add_item(element_tree, hf_value_element_dest_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
2707 proto_tree_add_item(element_tree, hf_value_element_src_port, tvb, offset, 2, ENC_BIG_ENDIAN);
2709 proto_tree_add_item(element_tree, hf_value_element_dest_port, tvb, offset, 2, ENC_BIG_ENDIAN);
2712 proto_tree_add_item(element_tree, hf_value_element_web_cache_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
2719 /* 6.14 Mask/Value Set Element */
2721 dissect_wccp2_mask_value_set_element(tvbuff_t *tvb, int offset, gint length, int idx, packet_info *pinfo, proto_tree *info_tree)
2723 proto_item *tl, *te;
2724 proto_tree *element_tree, *value_tree;
2725 guint num_of_val_elements;
2729 tl = proto_tree_add_text(info_tree, tvb, offset, 0,
2730 "Mask/Value Set Element(%d)", idx);
2731 element_tree = proto_item_add_subtree(tl, ett_mv_set_element);
2733 new_length = dissect_wccp2_mask_element(tvb,offset,length,pinfo,element_tree);
2734 NOTE_EATEN_LENGTH(new_length);
2739 num_of_val_elements = tvb_get_ntohl(tvb, offset);
2740 te = proto_tree_add_uint(element_tree, hf_mask_value_set_element_value_element_num, tvb, offset, 4, num_of_val_elements);
2742 value_tree = proto_item_add_subtree(te, ett_mv_set_value_list);
2745 for (i = 0; i < num_of_val_elements; i++)
2747 new_length=dissect_wccp2_value_element(tvb, offset, length, i, pinfo, value_tree);
2749 NOTE_EATEN_LENGTH(new_length);
2752 proto_item_set_len(tl, 16+num_of_val_elements*16);
2757 #define ALT_ASSIGNMENT_INFO_MIN_LEN (4+4)
2759 /* 5.4.2 Alternate Assignment Component */
2761 dissect_wccp2_alternate_assignment_info(tvbuff_t *tvb, int offset, gint length,
2762 packet_info *pinfo, proto_tree *info_tree)
2764 guint16 assignment_type;
2765 guint16 assignment_length;
2766 proto_item *tf=NULL;
2771 proto_tree *element_tree;
2775 if (length < ALT_ASSIGNMENT_INFO_MIN_LEN)
2776 return length - ALT_ASSIGNMENT_INFO_MIN_LEN;
2779 assignment_type = tvb_get_ntohs(tvb, offset);
2780 proto_tree_add_item(info_tree, hf_alt_assignment_info_assignment_type, tvb, offset, 2, ENC_BIG_ENDIAN);
2783 assignment_length = tvb_get_ntohs(tvb, offset);
2784 tf=proto_tree_add_item(info_tree, hf_alt_assignment_info_assignment_length, tvb, offset, 2, ENC_BIG_ENDIAN);
2787 if (length < assignment_length)
2788 expert_add_info_format(pinfo, tf, &ei_wccp_assignment_length_bad,
2789 "Assignment length is %d but only %d remain in the packet. Ignoring this for now",
2790 assignment_length, length);
2792 if (length > assignment_length) {
2793 expert_add_info_format(pinfo, tf, &ei_wccp_assignment_length_bad,
2794 "Assignment length is %d but %d remain in the packet. Assuming that the assignment length is wrong and setting it to %d.",
2795 assignment_length, length, length);
2798 new_length=dissect_wccp2_assignment_key_element(tvb, offset, length, pinfo, info_tree);
2799 NOTE_EATEN_LENGTH(new_length);
2801 n_routers = tvb_get_ntohl(tvb, offset);
2802 proto_tree_add_uint(info_tree, hf_alt_assignment_info_num_routers, tvb, offset, 4, n_routers);
2805 for (i = 0; i < n_routers; i++) {
2807 return length - 12*(n_routers-i);
2809 te = proto_tree_add_text(info_tree, tvb, offset, 12,
2810 "Router %d Assignment Element: IP address %s", i,
2811 decode_wccp_encoded_address(tvb, offset, pinfo, info_tree));
2813 element_tree = proto_item_add_subtree(te, ett_router_alt_assignment_element);
2814 dissect_wccp2_router_assignment_element(tvb, offset, length , pinfo, element_tree);
2818 switch (assignment_type) {
2819 case WCCP2_HASH_ASSIGNMENT_TYPE:
2820 return dissect_wccp2_hash_assignment_info(tvb, offset, length,
2822 case WCCP2_MASK_ASSIGNMENT_TYPE:
2823 return dissect_wccp2_mask_value_set_list(tvb, offset, length,
2825 case WCCP2r1_ALT_MASK_ASSIGNMENT_TYPE:
2826 return dissect_wccp2_alternate_mask_value_set_list(tvb, offset, length,
2836 /* End of utility functions */
2839 proto_register_wccp(void)
2841 static hf_register_info hf[] = {
2842 { &hf_wccp_message_type,
2843 { "WCCP Message Type", "wccp.message", FT_UINT32, BASE_DEC, VALS(wccp_type_vals), 0x0,
2844 "The WCCP message that was sent", HFILL }
2847 { "WCCP Version", "wccp.version", FT_UINT32, BASE_HEX, VALS(wccp_version_val), 0x0,
2848 "The WCCP version", HFILL }
2850 { &hf_message_header_version,
2851 { "WCCP Version (>=2)", "wccp.message_header_version", FT_UINT16, BASE_HEX, NULL, 0x0,
2852 "The WCCP version for version 2 and above", HFILL }
2854 { &hf_hash_revision,
2855 { "Hash Revision", "wccp.hash_revision", FT_UINT32, BASE_DEC, 0x0, 0x0,
2856 "The cache hash revision", HFILL }
2859 { "Change Number", "wccp.change_num", FT_UINT32, BASE_DEC, 0x0, 0x0,
2860 "The Web-Cache list entry change number", HFILL }
2863 { "Flags", "wccp.hash_flag", FT_UINT32, BASE_HEX, 0x0, 0x0,
2867 { "Hash information", "wccp.hash_flag.u", FT_BOOLEAN, 32, TFS(&tfs_historical_current), 0x10000,
2871 { "Received ID", "wccp.recvd_id", FT_UINT32, BASE_DEC, 0x0, 0x0,
2872 "The number of I_SEE_YOU's that have been sent", HFILL }
2875 { "Web Cache IP address", "wccp.cache_ip", FT_IPv4, BASE_NONE, NULL, 0x0,
2876 "The IP address of a Web cache", HFILL }
2879 { "Number of Web Caches", "wccp.wc_num", FT_UINT32, BASE_DEC, 0x0, 0x0,
2882 { &hf_message_header_length,
2883 { "Length", "wccp.message_header_length", FT_UINT16, BASE_DEC, 0x0, 0x0,
2887 { "Length", "wccp.item_length", FT_UINT16, BASE_DEC, 0x0, 0x0,
2888 "The Length ofthe WCCPv2 item", HFILL }
2891 { "Type", "wccp.item_type", FT_UINT16, BASE_DEC, VALS(info_type_vals), 0x0,
2892 "The type of the WCCPv2 item", HFILL }
2895 { "Data", "wccp.item_data", FT_BYTES, BASE_NONE, 0x0, 0x0,
2896 "The data for an unknown item type", HFILL }
2898 { &hf_security_info_option,
2899 { "Security Option", "wccp.security_info_option", FT_UINT16, BASE_DEC, VALS(security_option_vals), 0x0,
2902 { &hf_security_info_md5_checksum,
2903 { "MD5 checksum (not checked)", "wccp.security_md5_checksum", FT_BYTES, BASE_NONE, 0x0, 0x0,
2906 { &hf_command_element_type,
2907 {"Command Extension Type", "wccp.command_element_type", FT_UINT16, BASE_DEC, VALS(wccp_command_type_vals), 0x0,
2910 { &hf_command_element_length,
2911 {"Command Extension Length", "wccp.command_element_length", FT_UINT16, BASE_DEC, NULL, 0x0,
2914 { &hf_command_element_shutdown_ip,
2915 {"Command Extension Length", "wccp.command_element_shudown_ip", FT_UINT32, BASE_CUSTOM, wccp_fmt_ipadddress, 0x0,
2918 { &hf_service_info_type,
2919 { "Service Type", "wccp.service_info_type", FT_UINT8, BASE_DEC, VALS(service_type_vals), 0x0,
2922 { &hf_service_info_id_standard,
2923 { "WCCP Service ID (Standard)", "wccp.service_info_std_id", FT_UINT8, BASE_DEC, VALS(service_id_vals) , 0x0,
2924 "The WCCP Service id (Standard)", HFILL }
2926 { &hf_service_info_id_dynamic,
2927 { "WCCP Service ID ( Dynamic)", "wccp.service_info_dyn_id", FT_UINT8, BASE_DEC, NULL , 0x0,
2928 "The WCCP Service id (Dynamic)", HFILL }
2930 { &hf_service_info_priority,
2931 { "Priority (highest is 255)", "wccp.service_info_priority", FT_UINT8, BASE_DEC, NULL, 0x0,
2934 { &hf_service_info_protocol,
2935 { "Protocol", "wccp.service_info_protocol", FT_UINT8, BASE_DEC | BASE_EXT_STRING, &ipproto_val_ext, 0x0,
2938 { &hf_service_info_flags,
2939 { "Flags", "wccp.service_info_flags", FT_UINT32, BASE_HEX, 0x0, 0x0,
2942 { &hf_service_info_flags_src_ip_hash,
2943 { "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,
2946 { &hf_service_info_flags_dest_ip_hash,
2947 { "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,
2950 { &hf_service_info_flags_src_port_hash,
2951 { "Source port in primary hash", "wccp.service_info_flag.src_port_hash", FT_BOOLEAN, 32, TFS(&tfs_used_notused), WCCP2_SI_SRC_PORT_HASH,
2954 { &hf_service_info_flags_dest_port_hash,
2955 { "Destination port in primary hash", "wccp.service_info_flag.dest_port_hash", FT_BOOLEAN, 32, TFS(&tfs_used_notused), WCCP2_SI_DST_PORT_HASH,
2958 { &hf_service_info_flags_ports_defined,
2959 { "Ports", "wccp.service_info_flag.ports_defined", FT_BOOLEAN, 32, TFS(&tfs_defined_not_defined), WCCP2_SI_PORTS_DEFINED,
2962 { &hf_service_info_flags_ports_source,
2963 { "Ports refer to", "wccp.service_info_flag.ports_source", FT_BOOLEAN, 32, TFS(&tfs_src_dest_port), WCCP2_SI_PORTS_SOURCE,
2966 { &hf_service_info_flags_redirect_only_protocol_0,
2967 { "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,
2970 { &hf_service_info_flags_src_ip_alt_hash,
2971 { "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,
2974 { &hf_service_info_flags_dest_ip_alt_hash,
2975 { "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,
2978 { &hf_service_info_flags_src_port_alt_hash,
2979 { "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,
2982 { &hf_service_info_flags_dest_port_alt_hash,
2983 { "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,
2986 { &hf_service_info_source_port,
2987 { "Source Port", "wccp.service_info_source_port", FT_UINT16, BASE_DEC, NULL, 0x0,
2990 { &hf_service_info_destination_port,
2991 { "Destination Port", "wccp.service_info_destination_port", FT_UINT16, BASE_DEC, NULL, 0x0,
2994 { &hf_router_identity_ip,
2995 { "IP Address", "wccp.router_identity.ip", FT_UINT32, BASE_CUSTOM, wccp_fmt_ipadddress, 0x0,
2998 { &hf_router_identity_receive_id,
2999 { "Received ID", "wccp.router_identity.receive_id", FT_UINT32, BASE_DEC, 0x0, 0x0,
3002 { &hf_router_identity_send_to_ip,
3003 { "Sent To IP Address", "wccp.router_identity.send_to_ip", FT_UINT32, BASE_CUSTOM, wccp_fmt_ipadddress, 0x0,
3006 { &hf_router_identity_received_from_num,
3007 { "Number of Received From IP addresses (Webcache to which the message is directed)", "wccp.router.num_recv_ip", FT_UINT32, BASE_DEC, 0x0, 0x0,
3010 { &hf_web_cache_identity_ip,
3011 { "Web-Cache IP Address", "wccp.web_cache_identity.ip", FT_UINT32, BASE_CUSTOM, wccp_fmt_ipadddress, 0x0,
3014 { &hf_web_cache_identity_hash_rev,
3015 { "Hash Revision", "wccp.web_cache_identity.hash_rev", FT_UINT16, BASE_DEC, NULL, 0x0,
3018 { &hf_web_cache_identity_flags,
3019 { "Flags", "wccp.web_cache_identity.flags", FT_UINT16, BASE_HEX, NULL, 0x0,
3022 { &hf_web_cache_identity_flag_hash_info,
3023 { "Hash information", "wccp.web_cache_identity.flags.hash_info", FT_BOOLEAN, 16,
3024 TFS(&tfs_historical_current), 0x1,
3027 { &hf_web_cache_identity_flag_assign_type,
3028 { "Assignment Type", "wccp.web_cache_identity.flags.assign_type", FT_UINT16, BASE_HEX,
3029 VALS(&wccp_web_cache_assignment_data_type_val), 0x6,
3032 { &hf_web_cache_identity_flag_version_request,
3033 { "Version Request", "wccp.web_cache_identity.flags.version_request", FT_BOOLEAN, 16,
3034 TFS(&tfs_version_min_max), 0x8,
3037 { &hf_mask_value_set_element_value_element_num,
3038 { "Number of Value Elements", "wccp.mask_value_set_selement.value_element_num", FT_UINT32, BASE_DEC, 0x0, 0x0,
3041 { &hf_assignment_weight,
3042 { "Assignment Weight", "wccp.assignment_weight", FT_UINT16, BASE_DEC, NULL, 0x0,
3045 { &hf_assignment_status,
3046 { "Status", "wccp.assignment_status", FT_UINT16, BASE_HEX, NULL, 0x0,
3049 { &hf_assignment_key_ip,
3050 { "Assignment Key IP Address", "wccp.assignment_key.ip", FT_UINT32, BASE_CUSTOM, wccp_fmt_ipadddress, 0x0,
3053 { &hf_assignment_key_change_num,
3054 { "Assignment Key Change Number", "wccp.assignment_key.change_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3057 { &hf_router_view_member_change_num,
3058 { "Member Change Number", "wccp.router_view.member_change_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3061 { &hf_router_router_num,
3062 { "Number of Routers", "wccp.router_view.router_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3065 { &hf_router_identity_router_ip,
3066 { "Router IP Address", "wccp.router_identity.router_ip", FT_UINT32, BASE_CUSTOM, wccp_fmt_ipadddress, 0x0,
3069 { &hf_router_identity_received_from_ip,
3070 { "Received From IP Address/Target Web Cache IP", "wccp.router_identity.received_from_ip", FT_UINT32, BASE_CUSTOM, wccp_fmt_ipadddress, 0x0,
3073 { &hf_wc_view_info_change_num,
3074 { "Change Number", "wccp.wc_view_info.change_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3077 { &hf_wc_view_info_router_ip,
3078 { "Router IP", "wccp.wc_view_info.router_ip", FT_UINT32, BASE_CUSTOM, wccp_fmt_ipadddress, 0x0,
3081 { &hf_wc_view_info_wc_ip,
3082 { "Web Cache IP", "wccp.wc_view_info.wc_ip", FT_UINT32, BASE_CUSTOM, wccp_fmt_ipadddress, 0x0,
3085 { &hf_wc_view_router_num,
3086 { "Number of Routers", "wccp.wc_view_info.router_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3089 { &hf_wc_view_wc_num,
3090 { "Number of Web Caches", "wccp.wc_view_info.wc_num", FT_UINT32, BASE_DEC, 0x0, 0x0,
3093 { &hf_wc_identity_ip_address,
3094 { "Web Cache Identity", "wccp.hf_wc_identity_ip_address", FT_UINT32, BASE_CUSTOM, wccp_fmt_ipadddress, 0x0,
3095 "The IP identifying the Web Cache", HFILL }
3097 { &hf_router_assignment_element_change_num,
3098 { "Change Number", "wccp.router_assignment_element.change_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3101 { &hf_assignment_info_router_num,
3102 { "Number of Routers", "wccp.assignment_info.router_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3105 { &hf_assignment_info_router_ip,
3106 { "Router IP", "wccp.assignment_info.router_ip", FT_UINT32, BASE_CUSTOM, wccp_fmt_ipadddress, 0x0,
3109 { &hf_hash_buckets_assignment_wc_num,
3110 { "Number of WC", "wccp.hash_buckets_assignment.wc_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3113 { &hf_hash_buckets_assignment_wc_ip,
3114 { "WC IP", "wccp.hash_buckets_assignment.wc_ip", FT_UINT32, BASE_CUSTOM, wccp_fmt_ipadddress, 0x0,
3117 { &hf_router_view_ip,
3118 { "Router IP Address", "wccp.router_view.ip", FT_UINT32, BASE_CUSTOM, wccp_fmt_ipadddress, 0x0,
3121 { &hf_router_query_info_ip,
3122 { "Web-Cache Identity Element IP address", "wccp.router_query_info.ip", FT_UINT32, BASE_CUSTOM, wccp_fmt_ipadddress, 0x0,
3125 { &hf_router_query_info_send_to_ip,
3126 { "Sent To IP Address", "wccp.router_query_info.send_to_ip", FT_UINT32, BASE_CUSTOM, wccp_fmt_ipadddress, 0x0,
3129 { &hf_router_query_info_target_ip,
3130 { "Target IP Address", "wccp.router_query_info.target_ip", FT_UINT32, BASE_CUSTOM, wccp_fmt_ipadddress, 0x0,
3133 { &hf_capability_element_type,
3134 { "Type", "wccp.capability_element.type", FT_UINT16, BASE_DEC, VALS(capability_type_vals), 0x0,
3137 { &hf_capability_element_length,
3138 { "Value Length", "wccp.capability_element.length", FT_UINT16, BASE_DEC, NULL, 0x0,
3141 { &hf_capability_info_value,
3142 { "Value", "wccp.capability_info.value", FT_UINT32, BASE_HEX, NULL, 0x0,
3145 { &hf_capability_forwarding_method_flag_gre,
3146 { "GRE-encapsulated", "wccp.capability_info.forwarding_method_flag.gre", FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), WCCP2_FORWARDING_METHOD_GRE,
3149 { &hf_capability_forwarding_method_flag_l2,
3150 { "L2 rewrite", "wccp.capability_info.forwarding_method_flag.l2", FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), WCCP2_FORWARDING_METHOD_L2,
3153 { &hf_capability_assignment_method_flag_hash,
3154 { "Hash", "wccp.capability_info.assignment_method_flag.hash", FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), WCCP2_ASSIGNMENT_METHOD_HASH,
3157 { &hf_capability_assignment_method_flag_mask,
3158 { "Mask", "wccp.capability_info.assignment_method_flag.mask", FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), WCCP2_ASSIGNMENT_METHOD_MASK,
3161 { &hf_capability_return_method_flag_gre,
3162 { "GRE-encapsulated", "wccp.capability_info.return_method_flag.gre", FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), WCCP2_PACKET_RETURN_METHOD_GRE,
3165 { &hf_capability_return_method_flag_l2,
3166 { "L2 rewrite", "wccp.capability_info.return_method_flag.l2", FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), WCCP2_PACKET_RETURN_METHOD_L2,
3169 { &hf_capability_transmit_t,
3170 { "Message interval in milliseconds", "wccp.capability.transmit_t", FT_UINT16, BASE_DEC, NULL, 0x0,
3173 { &hf_capability_transmit_t_upper_limit,
3174 { "Message interval upper limit in milliseconds", "wccp.capability.transmit_t.upper_limit", FT_UINT16, BASE_DEC, NULL, 0x0,
3177 { &hf_capability_transmit_t_lower_limit,
3178 { "Message interval lower limit in milliseconds", "wccp.capability.transmit_t.upper_limit", FT_UINT16, BASE_DEC, NULL, 0x0,
3181 { &hf_capability_timer_scale_timeout_scale,
3182 { "Timer scale", "wccp.capability.timer_scale.timeout_scale", FT_UINT8, BASE_DEC, NULL, 0x0,
3185 { &hf_capability_timer_scale_timeout_scale_upper_limit,
3186 { "Timer scale upper limit", "wccp.capability.timer_scale.timeout_scale.upper_limit", FT_UINT8, BASE_DEC, NULL, 0x0,
3189 { &hf_capability_timer_scale_timeout_scale_lower_limit,
3190 { "Timer scale lower limit", "wccp.capability.timer_scale.timeout_scale.lower_limit", FT_UINT8, BASE_DEC, NULL, 0x0,
3193 { &hf_capability_timer_scale_ra_timer_scale,
3194 { "RA Timer scale", "wccp.capability.timer_scale.ra_timer_scale", FT_UINT8, BASE_DEC, NULL, 0x0,
3197 { &hf_capability_timer_scale_ra_scale_upper_limit,
3198 { "RA Timer scale upper limit", "wccp.capability.timer_scale.ra_timer_scale.upper_limit", FT_UINT8, BASE_DEC, NULL, 0x0,
3201 { &hf_capability_timer_scale_ra_scale_lower_limit,
3202 { "RA Timer scale lower limit", "wccp.capability.timer_scale.ra_timer_scale.lower_limit", FT_UINT8, BASE_DEC, NULL, 0x0,
3205 { &hf_value_element_src_ip,
3206 { "Source Address", "wccp.value_element.src_ip", FT_UINT32, BASE_CUSTOM, wccp_fmt_ipadddress, 0x0,
3209 { &hf_value_element_dest_ip,
3210 { "Destination Address", "wccp.value_element.dest_ip", FT_UINT32, BASE_CUSTOM, wccp_fmt_ipadddress, 0x0,
3213 { &hf_value_element_src_port,
3214 { "Source Port", "wccp.value_element.src_port", FT_UINT16, BASE_DEC, NULL, 0x0,
3217 { &hf_value_element_dest_port,
3218 { "Destination Port", "wccp.value_element.dest_port", FT_UINT16, BASE_DEC, NULL, 0x0,
3221 { &hf_value_element_web_cache_ip,
3222 { "Web Cache Address", "wccp.value_element.web_cache_ip", FT_UINT32, BASE_CUSTOM, wccp_fmt_ipadddress, 0x0,
3225 { &hf_mask_value_set_list_num_elements,
3226 { "Number of elements", "wccp.mask_value_set_list.num_elements", FT_UINT32, BASE_DEC, NULL, 0x0,
3229 { &hf_mask_element_src_ip,
3230 { "Source Address Mask", "wccp.mask_element.src_ip", FT_UINT32, BASE_HEX, NULL, 0x0,
3233 { &hf_mask_element_dest_ip,
3234 { "Destination Address Mask", "wccp.mask_element.dest_ip", FT_UINT32, BASE_HEX, NULL, 0x0,
3237 { &hf_mask_element_src_port,
3238 { "Source Port Mask", "wccp.mask_element.src_port", FT_UINT16, BASE_HEX, NULL, 0x0,
3241 { &hf_mask_element_dest_port,
3242 { "Destination Port Mask", "wccp.mask_element.dest_port", FT_UINT16, BASE_HEX, NULL, 0x0,
3245 { &hf_alt_assignment_info_assignment_type,
3246 { "Assignment type", "wccp.alt_assignment_info.assignment_type", FT_UINT16, BASE_DEC, VALS(assignment_type_vals), 0x0,
3249 { &hf_extended_assignment_data_type,
3250 { "Assignment type", "wccp.extended_assignment_data.type", FT_UINT16, BASE_DEC, VALS(assignment_type_vals), 0x0,
3253 { &hf_alt_assignment_map_assignment_type,
3254 { "Assignment type", "wccp.alt_assignment_map.assignment_type", FT_UINT16, BASE_DEC, VALS(assignment_type_vals), 0x0,
3257 { &hf_alt_assignment_map_assignment_length,
3258 { "Assignment length", "wccp.alt_assignment_map.assignment_length", FT_UINT16, BASE_DEC, NULL, 0x0,
3261 { &hf_alt_assignment_info_assignment_length,
3262 { "Assignment length", "wccp.alt_assignment_info.assignment_length", FT_UINT16, BASE_DEC, NULL, 0x0,
3265 { &hf_extended_assignment_data_length,
3266 { "Assignment length", "wccp.extended_assignment_data.length", FT_UINT16, BASE_DEC, NULL, 0x0,
3269 { &hf_alt_assignment_info_num_routers,
3270 { "Number of routers", "wccp.alt_assignment_info.num_routers", FT_UINT32, BASE_DEC, NULL, 0x0,
3273 { &hf_alt_assignment_mask_value_set_element_num_wc_value_elements,
3274 { "Number of Web-Cache Value Elements", "wccp.alt_assignment_mask_value_set_element.num_wc_value_elements", FT_UINT32, BASE_DEC, NULL, 0x0,
3277 { &hf_web_cache_value_element_wc_address,
3278 { "Web-Cache Address", "wccp.web_cache_value_element.wc_address", FT_UINT32, BASE_CUSTOM, wccp_fmt_ipadddress, 0x0,
3281 { &hf_web_cache_value_element_num_values,
3282 { "Number of Valye Sequence Numbers", "wccp.web_cache_value_element.num_values", FT_UINT32, BASE_DEC, NULL, 0x0,
3285 { &hf_alt_assignment_mask_value_set_list_num_elements,
3286 { "Number of Alternate Mask/Value Set Elements", "wccp.alt_assignment_mask_value_list.num_elements", FT_UINT32, BASE_DEC, NULL, 0x0,
3289 { &hf_address_table_family,
3290 { "Family Type", "wccp.address_table.family_type", FT_UINT16, BASE_DEC, VALS(wccp_address_family_val), 0x0,
3291 "The WCCP Address Table Family type", HFILL }
3293 { &hf_address_table_address_length,
3294 { "Address Length", "wccp.address_table.address_length", FT_UINT16, BASE_DEC, NULL, 0x0,
3295 "The WCCP Address Table Address Length", HFILL }
3297 { &hf_address_table_length,
3298 { "Length", "wccp.address_table.length", FT_UINT16, BASE_DEC, NULL, 0x0,
3299 "The WCCP Address Table Length", HFILL }
3301 { &hf_address_table_element,
3302 { "Address", "wccp.address_table.element", FT_STRING, BASE_NONE, NULL, 0x0,
3307 static gint *ett[] = {
3310 &ett_hash_assignment_buckets,
3311 &ett_mask_assignment_data_element,
3312 &ett_alternate_mask_assignment_data_element,
3313 &ett_extended_assigment_data_element,
3316 &ett_wc_identity_flags,
3321 &ett_service_info_ports,
3322 &ett_wc_view_info_router_element,
3323 &ett_router_identity_info,
3324 &ett_wc_identity_element,
3325 &ett_wc_identity_info,
3326 &ett_router_view_info,
3329 &ett_router_assignment_element,
3330 &ett_hash_buckets_assignment_wc_element,
3331 &ett_hash_buckets_assignment_buckets,
3332 &ett_router_alt_assignment_element,
3333 &ett_router_assignment_info,
3334 &ett_capabilities_info,
3335 &ett_capability_element,
3336 &ett_capability_forwarding_method,
3337 &ett_capability_assignment_method,
3338 &ett_capability_return_method,
3339 &ett_capability_transmit_t,
3340 &ett_capability_timer_scale,
3342 &ett_mv_set_element,
3343 &ett_mv_set_value_list,
3344 &ett_alternate_mv_set_element_list,
3345 &ett_web_cache_value_element_list,
3346 &ett_alternate_mv_set_element,
3348 &ett_alt_assignment_info,
3349 &ett_alt_assignment_map,
3350 &ett_assignment_map,
3353 &ett_alternate_mask_value_set,
3354 &ett_alternate_mask_value_set_element,
3355 &ett_command_extension,
3358 static ei_register_info ei[] = {
3359 { &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 }},
3360 { &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 }},
3361 { &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 }},
3362 { &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 }},
3363 { &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 }},
3364 { &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 }},
3365 { &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 }},
3366 { &ei_wccp_missing_assignment, { "wccp.missing.assignment", PI_PROTOCOL, PI_ERROR, "This message should contain a Alternate Assignment, Assignment Map, Assignment Info or "
3367 "Alternative Assignment Map component, but it is missing", EXPFILL }},
3368 { &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 }},
3369 { &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 }},
3370 { &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 }},
3371 { &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 }},
3372 { &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 }},
3373 { &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 }},
3374 { &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 }},
3375 { &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 }},
3376 { &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 }},
3377 { &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 }},
3378 { &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 }},
3379 { &ei_wccp_assignment_length_bad, { "wccp.assignment_length_bad", PI_PROTOCOL, PI_ERROR, "Assignment length bad", EXPFILL }},
3380 { &ei_wccp_length_bad, { "wccp.length_bad", PI_PROTOCOL, PI_ERROR, "Length bad", EXPFILL }},
3381 { &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 }},
3382 { &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 }},
3383 { &ei_wccp_router_identity_receive_id_zero, { "wccp.router_identity.receive_id.zero", PI_PROTOCOL, PI_WARN, "Receive ID shouldn't be 0", EXPFILL }},
3384 { &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 }},
3385 { &ei_wccp_address_table_family_unknown, { "wccp.address_table.family_type.unknown", PI_PROTOCOL, PI_ERROR, "Unknown address family", EXPFILL }},
3386 { &ei_wccp_capability_element_length, { "wccp.capability_element.length.invalid", PI_PROTOCOL, PI_WARN, "Value Length invalid", EXPFILL }},
3389 expert_module_t* expert_wccp;
3391 proto_wccp = proto_register_protocol("Web Cache Communication Protocol",
3393 proto_register_field_array(proto_wccp, hf, array_length(hf));
3394 proto_register_subtree_array(ett, array_length(ett));
3395 expert_wccp = expert_register_protocol(proto_wccp);
3396 expert_register_field_array(expert_wccp, ei, array_length(ei));
3400 proto_reg_handoff_wccp(void)
3402 dissector_handle_t wccp_handle;
3404 wccp_handle = new_create_dissector_handle(dissect_wccp, proto_wccp);
3405 dissector_add_uint("udp.port", UDP_PORT_WCCP, wccp_handle);
3409 * Editor modelines - http://www.wireshark.org/tools/modelines.html
3414 * indent-tabs-mode: nil
3417 * vi: set shiftwidth=2 tabstop=8 expandtab:
3418 * :indentSize=2:tabSize=8:noTabs=true: