Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-wccp.c
blob298b57aed336202ddbeb347a664883a7d2de43f4
1 /* packet-wccp.c
2 * Routines for Web Cache C* 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 * SPDX-License-Identifier: GPL-2.0-or-later
12 #include "config.h"
14 #include <epan/packet.h>
15 #include <epan/to_str.h>
16 #include <epan/ipproto.h>
17 #include <epan/expert.h>
18 #include <epan/tfs.h>
19 #include <wsutil/array.h>
20 #include "packet-wccp.h"
22 void proto_register_wccp(void);
23 void proto_reg_handoff_wccp(void);
25 static dissector_handle_t wccp_handle;
27 static int proto_wccp;
28 static int hf_wccp_message_type; /* the message type */
29 static int hf_wccp_version; /* protocol version */
30 static int hf_bucket;
31 static int hf_bucket_bit;
32 static int hf_message_header_version;
33 static int hf_hash_revision; /* the version of the hash */
34 static int hf_change_num; /* change number */
35 static int hf_hash_flag;
36 static int hf_hash_flag_u;
37 static int hf_recvd_id;
38 static int hf_wc_num;
39 static int hf_wc_view_wc_num;
40 static int hf_cache_ip;
41 static int hf_message_header_length;
42 static int hf_item_type;
43 static int hf_item_length;
44 static int hf_item_data;
45 static int hf_security_info_option;
46 static int hf_security_info_md5_checksum;
47 static int hf_command_element_type;
48 static int hf_command_element_length;
49 static int hf_command_length;
50 static int hf_command_element_shutdown_ip_index;
51 static int hf_command_element_shutdown_ipv4;
52 static int hf_command_element_shutdown_ipv6;
53 static int hf_command_unknown;
54 static int hf_service_info_type;
55 static int hf_service_info_id_standard;
56 static int hf_service_info_id_dynamic;
57 static int hf_service_info_priority;
58 static int hf_service_info_protocol;
59 static int hf_service_info_flags;
60 static int hf_service_info_flags_src_ip_hash;
61 static int hf_service_info_flags_dest_ip_hash;
62 static int hf_service_info_flags_src_port_hash;
63 static int hf_service_info_flags_dest_port_hash;
64 static int hf_service_info_flags_ports_defined;
65 static int hf_service_info_flags_ports_source;
66 static int hf_service_info_flags_redirect_only_protocol_0;
67 static int hf_service_info_flags_src_ip_alt_hash;
68 static int hf_service_info_flags_dest_ip_alt_hash;
69 static int hf_service_info_flags_src_port_alt_hash;
70 static int hf_service_info_flags_dest_port_alt_hash;
71 static int hf_service_info_flags_reserved;
72 static int hf_service_info_source_port;
73 static int hf_service_info_destination_port;
74 static int hf_router_identity_ip_index;
75 static int hf_router_identity_ipv4;
76 static int hf_router_identity_ipv6;
77 static int hf_router_identity_receive_id;
78 static int hf_router_identity_send_to_ip_index;
79 static int hf_router_identity_send_to_ipv4;
80 static int hf_router_identity_send_to_ipv6;
81 static int hf_router_identity_received_from_num;
82 static int hf_web_cache_identity_index;
83 static int hf_web_cache_identity_ipv4;
84 static int hf_web_cache_identity_ipv6;
85 static int hf_web_cache_identity_hash_rev;
86 static int hf_web_cache_identity_flags;
87 static int hf_web_cache_identity_flag_hash_info;
88 static int hf_web_cache_identity_flag_assign_type;
89 static int hf_web_cache_identity_flag_version_request;
90 static int hf_web_cache_identity_flag_reserved;
91 static int hf_mask_value_set_element_value_element_num;
92 static int hf_assignment_weight;
93 static int hf_assignment_status;
94 static int hf_assignment_key_ip_index;
95 static int hf_assignment_key_ipv4;
96 static int hf_assignment_key_ipv6;
97 static int hf_assignment_key_change_num;
98 static int hf_assignment_no_data;
99 static int hf_router_view_member_change_num;
100 static int hf_router_router_num;
101 static int hf_router_identity_router_ip_index;
102 static int hf_router_identity_router_ipv4;
103 static int hf_router_identity_router_ipv6;
104 static int hf_wc_view_info_change_num;
105 static int hf_wc_view_info_router_ip_index;
106 static int hf_wc_view_info_router_ipv4;
107 static int hf_wc_view_info_router_ipv6;
108 static int hf_wc_view_info_wc_ip_index;
109 static int hf_wc_view_info_wc_ipv4;
110 static int hf_wc_view_info_wc_ipv6;
111 static int hf_wc_view_router_num;
112 static int hf_wc_identity_ip_address_index;
113 static int hf_wc_identity_ip_address_ipv4;
114 static int hf_wc_identity_ip_address_ipv6;
115 static int hf_router_identity_received_from_ip_index;
116 static int hf_router_identity_received_from_ipv4;
117 static int hf_router_identity_received_from_ipv6;
118 static int hf_router_assignment_element_change_num;
119 static int hf_assignment_info_router_num;
120 static int hf_hash_buckets_assignment_wc_num;
121 static int hf_hash_buckets_assignment_wc_ip_index;
122 static int hf_hash_buckets_assignment_wc_ipv4;
123 static int hf_hash_buckets_assignment_wc_ipv6;
124 static int hf_assignment_info_router_ip_index;
125 static int hf_assignment_info_router_ipv4;
126 static int hf_assignment_info_router_ipv6;
127 static int hf_router_view_ip_index;
128 static int hf_router_view_ipv4;
129 static int hf_router_view_ipv6;
130 static int hf_router_query_info_ip_index;
131 static int hf_router_query_info_ipv4;
132 static int hf_router_query_info_ipv6;
133 static int hf_router_query_info_send_to_ip_index;
134 static int hf_router_query_info_send_to_ipv4;
135 static int hf_router_query_info_send_to_ipv6;
136 static int hf_router_query_info_target_ip_index;
137 static int hf_router_query_info_target_ipv4;
138 static int hf_router_query_info_target_ipv6;
139 static int hf_capability_element_type;
140 static int hf_capability_element_length;
141 static int hf_capability_info_value;
142 static int hf_capability_forwarding_method_flag_gre;
143 static int hf_capability_forwarding_method_flag_l2;
144 static int hf_capability_assignment_method_flag_hash;
145 static int hf_capability_assignment_method_flag_mask;
146 static int hf_capability_return_method_flag_gre;
147 static int hf_capability_return_method_flag_l2;
148 static int hf_capability_transmit_t;
149 static int hf_capability_transmit_t_upper_limit;
150 static int hf_capability_transmit_t_lower_limit;
151 static int hf_capability_timer_scale_timeout_scale;
152 static int hf_capability_timer_scale_ra_timer_scale;
153 static int hf_capability_timer_scale_timeout_scale_upper_limit;
154 static int hf_capability_timer_scale_timeout_scale_lower_limit;
155 static int hf_capability_timer_scale_ra_scale_upper_limit;
156 static int hf_capability_timer_scale_ra_scale_lower_limit;
157 static int hf_capability_value;
158 static int hf_reserved_zero;
159 static int hf_value_element_src_ip_index;
160 static int hf_value_element_src_ipv4;
161 static int hf_value_element_src_ipv6;
162 static int hf_value_element_dest_ip_index;
163 static int hf_value_element_dest_ipv4;
164 static int hf_value_element_dest_ipv6;
165 static int hf_value_element_src_port;
166 static int hf_value_element_dest_port;
167 static int hf_value_element_web_cache_ip_index;
168 static int hf_value_element_web_cache_ipv4;
169 static int hf_value_element_web_cache_ipv6;
170 static int hf_mask_value_set_list_num_elements;
171 static int hf_mask_element_src_ip;
172 static int hf_mask_element_dest_ip;
173 static int hf_mask_element_src_port;
174 static int hf_mask_element_dest_port;
175 static int hf_alt_assignment_info_assignment_type;
176 static int hf_extended_assignment_data_type;
177 static int hf_alt_assignment_info_assignment_length;
178 static int hf_alt_assignment_map_assignment_type;
179 static int hf_alt_assignment_map_assignment_length;
180 static int hf_extended_assignment_data_length;
181 static int hf_alt_assignment_info_num_routers;
182 static int hf_alt_assignment_mask_value_set_element_num_wc_value_elements;
183 static int hf_web_cache_value_element_wc_address_index;
184 static int hf_web_cache_value_element_wc_address_ipv4;
185 static int hf_web_cache_value_element_wc_address_ipv6;
186 static int hf_web_cache_value_element_num_values;
187 static int hf_web_cache_value_seq_num;
188 static int hf_alt_assignment_mask_value_set_list_num_elements;
189 static int hf_address_table_family;
190 static int hf_address_table_address_length;
191 static int hf_address_table_length;
192 static int hf_address_table_element;
194 static int ett_wccp;
195 static int ett_buckets;
196 static int ett_hash_assignment_buckets;
197 static int ett_mask_assignment_data_element;
198 static int ett_alternate_mask_assignment_data_element;
199 static int ett_extended_assigment_data_element;
200 static int ett_table_element;
201 static int ett_hash_flags;
202 static int ett_wc_identity_flags;
203 static int ett_cache_info;
204 static int ett_security_info;
205 static int ett_service_info;
206 static int ett_service_flags;
207 static int ett_service_info_ports;
208 static int ett_wc_view_info_router_element;
209 static int ett_router_identity_info;
210 static int ett_wc_identity_element;
211 static int ett_wc_identity_info;
212 static int ett_router_view_info;
213 static int ett_wc_view_info;
214 static int ett_router_assignment_element;
215 static int ett_hash_buckets_assignment_wc_element;
216 static int ett_hash_buckets_assignment_buckets;
217 static int ett_router_alt_assignment_element;
218 static int ett_router_assignment_info;
219 static int ett_query_info;
220 static int ett_capabilities_info;
221 static int ett_capability_element;
222 static int ett_capability_forwarding_method;
223 static int ett_capability_assignment_method;
224 static int ett_capability_return_method;
225 static int ett_capability_transmit_t;
226 static int ett_capability_timer_scale;
227 static int ett_alt_assignment_info;
228 static int ett_alt_assignment_map;
229 static int ett_address_table;
230 static int ett_assignment_map;
231 static int ett_command_extension;
232 static int ett_alternate_mask_value_set;
233 static int ett_alternate_mask_value_set_element;
234 static int ett_mv_set_list;
235 static int ett_mv_set_element;
236 static int ett_mv_set_value_list;
237 static int ett_alternate_mv_set_element_list;
238 static int ett_web_cache_value_element_list;
239 static int ett_alternate_mv_set_element;
240 static int ett_value_element;
241 static int ett_unknown_info;
243 static expert_field ei_wccp_missing_security_info;
244 static expert_field ei_wccp_missing_service_info;
245 static expert_field ei_wccp_missing_wc_id_info;
246 static expert_field ei_wccp_missing_router_id_info;
247 static expert_field ei_wccp_missing_query_info;
248 static expert_field ei_wccp_missing_wc_view_info;
249 static expert_field ei_wccp_missing_rtr_view_info;
250 static expert_field ei_wccp_contains_redirect_assignment;
251 static expert_field ei_wccp_contains_router_id_info;
252 static expert_field ei_wccp_contains_rtr_view_info;
253 static expert_field ei_wccp_contains_query_info;
254 static expert_field ei_wccp_contains_alt_assignment;
255 static expert_field ei_wccp_contains_assign_map;
256 static expert_field ei_wccp_contains_alt_assignment_map;
257 static expert_field ei_wccp_contains_wc_id_info;
258 static expert_field ei_wccp_contains_wc_view_info;
259 static expert_field ei_wccp_contains_capabilities_info;
260 static expert_field ei_wccp_contains_command_extension;
261 static expert_field ei_wccp_missing_assignment;
262 static expert_field ei_wccp_assignment_length_bad;
263 static expert_field ei_wccp_length_bad;
264 static expert_field ei_wccp_service_info_priority_nonzero;
265 static expert_field ei_wccp_service_info_protocol_nonzero;
266 static expert_field ei_wccp_router_identity_receive_id_zero;
267 static expert_field ei_wccp_web_cache_identity_hash_rev_zero;
268 static expert_field ei_wccp_address_table_family_unknown;
269 static expert_field ei_wccp_capability_element_length;
270 static expert_field ei_wccp_port_fields_not_used;
271 static expert_field ei_wccp_a_zero_not_c;
272 /* static expert_field ei_wccp_c_zero_not_a; */
275 * At
277 * https://datatracker.ietf.org/doc/html/draft-forster-wrec-wccp-v1-00
279 * is the now-expired Internet-Draft for WCCP 1.0 (Web Cache Coordination
280 * Protocol V1.0).
282 * At
284 * https://datatracker.ietf.org/doc/html/draft-wilson-wrec-wccp-v2-01
286 * is the now-expired Internet-Draft for WCCP 2.0 (Web Cache Communication
287 * Protocol V2.0).
289 * https://datatracker.ietf.org/doc/html/draft-param-wccp-v2rev1-01
291 * is the now-expired Internet-Draft for WCCP 2.01 (Web Cache Communication
292 * Protocol V2, Revision 1).
295 /* This is NOT IANA assigned */
296 #define UDP_PORT_WCCP 2048
298 #define WCCPv1 4
299 #define WCCPv2 0x0200
300 #define WCCPv2r1 0x0201
301 #define WCCP_HERE_I_AM 7
302 #define WCCP_I_SEE_YOU 8
303 #define WCCP_ASSIGN_BUCKET 9
304 #define WCCP2_HERE_I_AM 10
305 #define WCCP2_I_SEE_YOU 11
306 #define WCCP2_REDIRECT_ASSIGN 12
307 #define WCCP2_REMOVAL_QUERY 13
309 static const value_string wccp_type_vals[] = {
310 { WCCP_HERE_I_AM, "1.0 Here I am" },
311 { WCCP_I_SEE_YOU, "1.0 I see you" },
312 { WCCP_ASSIGN_BUCKET, "1.0 Assign bucket" },
313 { WCCP2_HERE_I_AM, "2.0 Here I am" },
314 { WCCP2_I_SEE_YOU, "2.0 I see you" },
315 { WCCP2_REDIRECT_ASSIGN, "2.0 Redirect assign" },
316 { WCCP2_REMOVAL_QUERY, "2.0 Removal query" },
317 { 0, NULL }
320 static const value_string wccp_version_val[] = {
321 { WCCPv1, "1"},
322 { WCCPv2, "2"},
323 { WCCPv2r1, "2.01"},
324 { 0, NULL}
327 static const true_false_string tfs_src_dest_port = { "Source port", "Destination port" };
328 static const true_false_string tfs_redirect_protocol0 = { "Redirect only protocol 0 (IP)", "Redirect all traffic" };
329 static const true_false_string tfs_historical_current = { "Historical", "Current" };
330 static const true_false_string tfs_version_min_max = {"WCCP version set is maximum supported by CE", "WCCP version set is minimum supported by CE"};
332 static const value_string wccp_address_family_val[] = {
333 { 0, "Reserved" },
334 { 1, "IPv4" },
335 { 2, "IPv6" },
336 { 0, NULL }
340 #define WCCP2_HASH_ASSIGNMENT_TYPE 0
341 #define WCCP2_MASK_ASSIGNMENT_TYPE 1
342 #define WCCP2r1_ALT_MASK_ASSIGNMENT_TYPE 2
343 #define WCCP2r1_ASSIGNMENT_WEIGHT_STATUS 3
345 static const value_string assignment_type_vals[] = {
346 { WCCP2_HASH_ASSIGNMENT_TYPE, "Hash" },
347 { WCCP2_MASK_ASSIGNMENT_TYPE, "Mask" },
348 { WCCP2r1_ALT_MASK_ASSIGNMENT_TYPE, "WCCP2r1 Alternate Mask"},
349 { WCCP2r1_ASSIGNMENT_WEIGHT_STATUS, "WCCP2r1 Assignment Weight Status"},
350 { 0, NULL }
353 #define HASH_INFO_SIZE (4*(1+8+1))
355 #define WCCP2_SECURITY_INFO 0
356 #define WCCP2_SERVICE_INFO 1
357 #define WCCP2_ROUTER_ID_INFO 2
358 #define WCCP2_WC_ID_INFO 3
359 #define WCCP2_RTR_VIEW_INFO 4
360 #define WCCP2_WC_VIEW_INFO 5
361 #define WCCP2_REDIRECT_ASSIGNMENT 6
362 #define WCCP2_QUERY_INFO 7
363 #define WCCP2_CAPABILITIES_INFO 8
364 #define WCCP2_ALT_ASSIGNMENT 13
365 #define WCCP2_ASSIGN_MAP 14
366 #define WCCP2_COMMAND_EXTENSION 15
367 /* WCCP 2 r1 additions: */
368 #define WCCP2r1_ALT_ASSIGNMENT_MAP 16
369 #define WCCP2r1_ADDRESS_TABLE 17
371 static const value_string info_type_vals[] = {
372 { WCCP2_SECURITY_INFO, "Security Info" },
373 { WCCP2_SERVICE_INFO, "Service Info" },
374 { WCCP2_ROUTER_ID_INFO, "Router Identity Info" },
375 { WCCP2_WC_ID_INFO, "Web-Cache Identity Info" },
376 { WCCP2_RTR_VIEW_INFO, "Router View Info" },
377 { WCCP2_WC_VIEW_INFO, "Web-Cache View Info" },
378 { WCCP2_REDIRECT_ASSIGNMENT, "Assignment Info" },
379 { WCCP2_QUERY_INFO, "Router Query Info" },
380 { WCCP2_CAPABILITIES_INFO, "Capabilities Info" },
381 { WCCP2_ALT_ASSIGNMENT, "Alternate Assignment" },
382 { WCCP2_ASSIGN_MAP, "Assignment Map" },
383 { WCCP2_COMMAND_EXTENSION, "Command Extension" },
384 { WCCP2r1_ALT_ASSIGNMENT_MAP, "Alternative Assignment Map" },
385 { WCCP2r1_ADDRESS_TABLE, "Address Table" },
386 { 0, NULL }
389 const value_string service_id_vals[] = {
390 { 0x00, "HTTP" },
391 { 0, NULL }
394 typedef struct capability_flag {
395 uint32_t value;
396 const char *short_name;
397 int* phf;
398 } capability_flag;
403 #define WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_HASH 0
404 #define WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_MASK 1
405 #define WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_NOT_PRESENT 2
406 #define WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_EXTENDED 3
408 static const value_string wccp_web_cache_assignment_data_type_val[] = {
409 { WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_HASH , "Hash Assignment Data Element"},
410 { WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_MASK , "Mask Assignment Data Element"},
411 { WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_NOT_PRESENT , "Assignment Data Element Not Present"},
412 { WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_EXTENDED , "Extended Assignment Data Element"},
413 { 0, NULL }
416 #define WCCP2_FORWARDING_METHOD 0x01
417 #define WCCP2_ASSIGNMENT_METHOD 0x02
418 #define WCCP2_PACKET_RETURN_METHOD 0x03
419 #define WCCP2_TRANSMIT_T 0x04
420 #define WCCP2_TIMER_SCALE 0x05
422 static const value_string capability_type_vals[] = {
423 { WCCP2_FORWARDING_METHOD, "Forwarding Method" },
424 { WCCP2_ASSIGNMENT_METHOD, "Assignment Method" },
425 { WCCP2_PACKET_RETURN_METHOD, "Packet Return Method" },
426 { WCCP2_TRANSMIT_T, "Transmit_t Message interval values"},
427 { WCCP2_TIMER_SCALE, "Timer_scale Timeout scale values"},
428 { 0, NULL }
432 /* with version 2.01 we now have a address table which is possibly present */
434 typedef struct wccp_address_table {
435 bool in_use;
436 int16_t family;
437 int16_t version;
438 uint16_t table_length;
439 ws_in4_addr *table_ipv4;
440 ws_in6_addr *table_ipv6;
441 } wccp_address_table;
443 static int wccp_bucket_info(uint8_t bucket_info, proto_tree *bucket_tree,
444 uint32_t start, tvbuff_t *tvb, int offset);
446 /* The V2 dissectors will return the remaining length of the packet
447 and a negative number if there are missing bytes to finish the
448 dissection */
449 static int dissect_wccp2_mask_assignment_data_element(tvbuff_t *tvb, int offset, int length, packet_info *pinfo,
450 proto_tree *info_tree, wccp_address_table* addr_table);
451 static int dissect_wccp2_hash_buckets_assignment_element(tvbuff_t *tvb, int offset, int length,
452 packet_info *pinfo, proto_tree *info_tree, wccp_address_table* addr_table);
453 static int dissect_wccp2r1_address_table_info(tvbuff_t *tvb, int offset,
454 int length, packet_info *pinfo, proto_tree *info_tree,
455 wccp_address_table* wccp_wccp_address_table);
456 static int dissect_wccp2_hash_assignment_data_element(tvbuff_t *tvb, int offset, int length, packet_info *pinfo,
457 proto_tree *info_tree);
458 static int dissect_wccp2_assignment_weight_and_status_element(tvbuff_t *tvb, int offset, int length, packet_info *pinfo,
459 proto_tree *info_tree);
460 static int dissect_wccp2_extended_assignment_data_element(tvbuff_t *tvb, int offset, int length, packet_info *pinfo,
461 proto_tree *info_tree, wccp_address_table* addr_table);
462 static int dissect_wccp2_capability_element(tvbuff_t *tvb, int offset, int length,
463 packet_info *pinfo _U_, proto_tree *info_tree);
464 static int dissect_wccp2_mask_value_set_list(tvbuff_t *tvb, int offset,
465 int length, packet_info *pinfo, proto_tree *info_tree, wccp_address_table* addr_table);
467 /* Utility functions */
468 static int dissect_wccp2_mask_value_set_element(tvbuff_t *tvb, int offset,
469 int length, int idx, packet_info *pinfo, proto_tree *info_tree, wccp_address_table* addr_table);
470 static int dissect_wccp2_alternate_mask_value_set_list(tvbuff_t *tvb, int offset,
471 int length, packet_info *pinfo _U_, proto_tree *info_tree, wccp_address_table* addr_table);
472 static int dissect_wccp2_alternate_mask_value_set_element(tvbuff_t *tvb, int offset, int length, unsigned el_index, packet_info *pinfo,
473 proto_tree *info_tree, wccp_address_table* addr_table);
474 static int dissect_wccp2_web_cache_value_element(tvbuff_t *tvb, int offset,
475 int length, packet_info *pinfo, proto_tree *info_tree, wccp_address_table* addr_table);
476 static void dissect_32_bit_capability_flags(tvbuff_t *tvb, int curr_offset,
477 uint16_t capability_val_len, int ett, const capability_flag *flags,
478 proto_tree *element_tree, proto_item *header,
479 proto_item *length_item, packet_info *pinfo);
480 static void dissect_transmit_t_capability(tvbuff_t *tvb, proto_item *te, int curr_offset,
481 uint16_t capability_val_len, int ett, proto_tree *element_tree,
482 proto_item *length_item, packet_info *pinfo);
483 static void dissect_timer_scale_capability(tvbuff_t *tvb, int curr_offset,
484 uint16_t capability_val_len, int ett, proto_tree *element_tree,
485 proto_item *length_item, packet_info *pinfo);
491 * In WCCP 2.01 addresses are encoded to support IPv6 with 32 bit fields
493 * handle the decoding
496 static void
497 find_wccp_address_table(tvbuff_t *tvb, int offset,
498 packet_info *pinfo, proto_tree *wccp_tree _U_, wccp_address_table* wccp_wccp_address_table)
500 uint16_t type;
501 uint16_t item_length;
503 for (;;) {
504 if (4 > tvb_reported_length_remaining(tvb, offset)) {
505 /* We've run out of packet data without finding an address table,
506 so there's no address table in the packet. */
507 return;
509 type = tvb_get_ntohs(tvb, offset);
510 item_length = tvb_get_ntohs(tvb, offset+2);
512 if ((item_length + 4) > tvb_reported_length_remaining(tvb, offset)) {
513 /* We've run out of packet data without finding an address table,
514 so there's no address table in the packet. */
515 return;
518 if (type == WCCP2r1_ADDRESS_TABLE)
520 dissect_wccp2r1_address_table_info(tvb, offset+4, item_length, pinfo, NULL, wccp_wccp_address_table);
521 /* no need to decode the rest */
522 return;
525 offset = offset + (item_length + 4);
530 /* This function prints the IP or the encoded IP if the table exists */
532 /* at most an IPv6 IP: see
533 http://stackoverflow.com/questions/166132/maximum-length-of-the-textual-representation-of-an-ipv6-address
535 39 = 8 groups of 4 digits with 7 : characters
539 45 = IPv4 tunnel features: 0000:0000:0000:0000:0000:0000:192.168.0.1
542 /* problem here is that the IP is in network byte order for IPv4
543 we need to fix that
546 static const char * decode_wccp_encoded_address(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
547 proto_tree *info_tree _U_, wccp_address_table* addr_table)
549 uint32_t host_addr;
550 char *buffer;
552 /* are we using an address table? */
553 if (!addr_table->in_use)
555 /* no; return the IPv4 IP */
556 host_addr = tvb_get_ipv4(tvb,offset);
557 buffer = (char *) wmem_alloc(wmem_packet_scope(), WS_INET_ADDRSTRLEN);
558 ip_addr_to_str_buf(&host_addr, buffer, WS_INET_ADDRSTRLEN);
560 else
562 /* yes; we need to decode the encoded address */
563 uint16_t reserv;
564 uint16_t addr_index;
566 host_addr = tvb_get_ntohl(tvb,offset);
567 reserv = (host_addr & 0xFFFF0000) >> 16;
568 addr_index = (host_addr & 0x0000FFFF);
570 if (reserv != 0) {
571 buffer = wmem_strdup(wmem_packet_scope(), "INVALID: reserved part non zero");
573 else {
574 /* now check if it's IPv4 or IPv6 we need to print */
575 switch (addr_table->family) {
576 case 1:
577 /* IPv4 */
579 /* special case: index 0 -> undefined IP */
580 if (addr_index == 0) {
581 buffer = wmem_strdup(wmem_packet_scope(), "0.0.0.0");
582 break;
584 /* are we be beyond the end of the table? */
585 if (addr_index > addr_table->table_length) {
586 buffer = wmem_strdup_printf(wmem_packet_scope(), "INVALID IPv4 index: %d > %d",
587 addr_index, addr_table->table_length);
588 break;
591 /* ok get the IP */
592 if (addr_table->table_ipv4 != NULL) {
593 buffer = (char *) wmem_alloc(wmem_packet_scope(), WS_INET_ADDRSTRLEN);
594 ip_addr_to_str_buf(&addr_table->table_ipv4[addr_index-1], buffer, WS_INET_ADDRSTRLEN);
596 else {
597 buffer = wmem_strdup(wmem_packet_scope(), "INVALID IPv4 table empty!");
599 break;
600 case 2:
601 /* IPv6 */
602 /* special case: index 0 -> undefined IP */
603 if (addr_index == 0) {
604 buffer = wmem_strdup(wmem_packet_scope(), "::");
605 break;
608 /* are we be beyond the end of the table? */
609 if (addr_index > addr_table->table_length) {
610 buffer = wmem_strdup_printf(wmem_packet_scope(), "INVALID IPv6 index: %d > %d",
611 addr_index, addr_table->table_length);
612 break;
615 /* ok get the IP */
616 if (addr_table->table_ipv6 != NULL) {
617 buffer = (char *) wmem_alloc(wmem_packet_scope(), WS_INET6_ADDRSTRLEN);
618 ip6_to_str_buf(&(addr_table->table_ipv6[addr_index-1]), buffer, WS_INET6_ADDRSTRLEN);
620 else {
621 buffer = wmem_strdup(wmem_packet_scope(), "INVALID IPv6 table empty!");
623 break;
624 default:
625 buffer = wmem_strdup(wmem_packet_scope(), "INVALID IP family");
626 break;
631 return buffer;
634 static proto_item* wccp_add_ipaddress_item(proto_tree* tree, int hf_index, int hf_ipv4, int hf_ipv6, tvbuff_t *tvb,
635 int offset, int length, wccp_address_table* addr_table)
637 uint32_t host_addr;
638 ws_in6_addr ipv6_zero;
639 uint16_t reserv, addr_index;
641 /* are we using an address table? */
642 if (! addr_table->in_use)
643 return proto_tree_add_item(tree, hf_ipv4, tvb, offset, length, ENC_BIG_ENDIAN);
645 host_addr = tvb_get_ntohl(tvb, offset);
647 /* we need to decode the encoded address: */
648 reserv = (host_addr & 0xFFFF0000) >> 16;
649 addr_index = (host_addr & 0x0000FFFF);
651 memset(&ipv6_zero, 0, sizeof(ipv6_zero));
653 if (reserv != 0)
654 return proto_tree_add_uint_format_value(tree, hf_index, tvb, offset, length, host_addr, "INVALID: reserved part non zero");
656 /* now check if it's IPv4 or IPv6 we need to print */
657 switch (addr_table->family) {
658 case 1:
659 /* IPv4 */
661 /* special case: index 0 -> undefined IP */
662 if (addr_index == 0) {
663 return proto_tree_add_item(tree, hf_ipv4, tvb, offset, length, ENC_LITTLE_ENDIAN);
665 /* are we be beyond the end of the table? */
666 if (addr_index > addr_table->table_length) {
667 return proto_tree_add_uint_format_value(tree, hf_index, tvb, offset, length, host_addr,
668 "INVALID IPv4 index: %d > %d", addr_index, addr_table->table_length);
671 /* ok get the IP */
672 if (addr_table->table_ipv4 != NULL) {
673 return proto_tree_add_ipv4(tree, hf_ipv4, tvb, offset, length, addr_table->table_ipv4[addr_index-1]);
676 return proto_tree_add_uint_format_value(tree, hf_index, tvb, offset, length, host_addr, "INVALID: IPv4 table empty!");
678 case 2:
679 /* IPv6 */
680 /* special case: index 0 -> undefined IP */
681 if (addr_index == 0) {
682 return proto_tree_add_ipv6(tree, hf_ipv6, tvb, offset, length, &ipv6_zero);
685 /* are we be beyond the end of the table? */
686 if (addr_index > addr_table->table_length) {
687 return proto_tree_add_uint_format_value(tree, hf_index, tvb, offset, length, host_addr,
688 "INVALID IPv6 index: %d > %d", addr_index, addr_table->table_length);
691 /* ok get the IP */
692 if (addr_table->table_ipv6 != NULL) {
693 return proto_tree_add_ipv6(tree, hf_ipv6, tvb, offset, length, &(addr_table->table_ipv6[addr_index-1]));
696 return proto_tree_add_uint_format_value(tree, hf_index, tvb, offset, length, host_addr,
697 "INVALID IPv6 table empty!");
700 return proto_tree_add_ipv4_format(tree, hf_index, tvb, offset, length, host_addr, "INVALID IP family");
703 #define WCCP_IP_MAX_LENGTH (WS_INET_ADDRSTRLEN > 46 ? WS_INET_ADDRSTRLEN : 46)
706 static unsigned
707 dissect_hash_data(tvbuff_t *tvb, int offset, proto_tree *wccp_tree)
709 proto_tree *bucket_tree;
710 proto_item *tf;
711 proto_tree *field_tree;
712 int i;
713 uint8_t bucket_info;
714 int n;
716 proto_tree_add_item(wccp_tree, hf_hash_revision, tvb, offset, 4,
717 ENC_BIG_ENDIAN);
718 offset += 4;
720 bucket_tree = proto_tree_add_subtree(wccp_tree, tvb, offset, 32,
721 ett_buckets, NULL, "Hash information");
723 for (i = 0, n = 0; i < 32; i++) {
724 bucket_info = tvb_get_uint8(tvb, offset);
725 n = wccp_bucket_info(bucket_info, bucket_tree, n, tvb, offset);
726 offset += 1;
728 tf = proto_tree_add_item(wccp_tree, hf_hash_flag, tvb, offset, 4, ENC_BIG_ENDIAN);
729 field_tree = proto_item_add_subtree(tf, ett_hash_flags);
730 proto_tree_add_item(field_tree, hf_hash_flag_u, tvb, offset, 4, ENC_BIG_ENDIAN);
731 offset += 4;
732 return offset;
735 static unsigned
736 dissect_web_cache_list_entry(tvbuff_t *tvb, int offset, int idx,
737 proto_tree *wccp_tree)
739 proto_tree *list_entry_tree;
741 list_entry_tree = proto_tree_add_subtree_format(wccp_tree, tvb, offset, 4 + HASH_INFO_SIZE,
742 ett_cache_info, NULL, "Web-Cache List Entry(%d)", idx);
743 proto_tree_add_item(list_entry_tree, hf_cache_ip, tvb, offset, 4,
744 ENC_BIG_ENDIAN);
745 offset += 4;
746 offset = dissect_hash_data(tvb, offset, list_entry_tree);
747 return offset;
751 * wccp_bucket_info()
752 * takes an integer representing a "Hash Information" bitmap, and spits out
753 * the corresponding proto_tree entries, returning the next bucket number.
755 static int
756 wccp_bucket_info(uint8_t bucket_info, proto_tree *bucket_tree, uint32_t start,
757 tvbuff_t *tvb, int offset)
759 uint32_t i;
761 for(i = 0; i < 8; i++) {
762 proto_tree_add_uint_format(bucket_tree, hf_bucket_bit, tvb, offset, 1, bucket_info & 1<<i,
763 "Bucket %3d: %s", start, (bucket_info & 1<<i ? "Assigned" : "Not Assigned") );
764 start++;
766 return start;
770 /* the following functions all need to check the length and the offset
771 so we have a few macros to use
774 #define EAT(x) {length -= x; offset += x;}
776 #define EAT_AND_CHECK(x,next) {length -= x; offset += x; if (length < next) return length - next;}
778 #define CHECK_LENGTH_ADVANCE_OFFSET(new_length) { \
779 int old_offset = offset; \
780 if (new_length<0) return new_length; \
781 offset += length-new_length; \
782 if (old_offset >= offset) return offset - old_offset; \
783 length = new_length; \
787 /* 5.1.1 Security Info Component */
789 /* Security options */
791 #define WCCP2_NO_SECURITY 0
792 #define WCCP2_MD5_SECURITY 1
794 #define SECURITY_INFO_LEN 4
796 static const value_string security_option_vals[] = {
797 { WCCP2_NO_SECURITY, "None" },
798 { WCCP2_MD5_SECURITY, "MD5" },
799 { 0, NULL }
803 static int
804 dissect_wccp2_security_info(tvbuff_t *tvb, int offset, int length,
805 packet_info *pinfo _U_, proto_tree *info_tree, wccp_address_table* addr_table _U_)
807 uint32_t security_option;
809 if (length < SECURITY_INFO_LEN)
810 return (length-SECURITY_INFO_LEN);
812 security_option = tvb_get_ntohl(tvb, offset);
813 proto_tree_add_item(info_tree, hf_security_info_option, tvb, offset, 4, ENC_BIG_ENDIAN);
815 if (security_option == WCCP2_MD5_SECURITY) {
816 offset += 4;
818 proto_tree_add_item(info_tree, hf_security_info_md5_checksum, tvb, offset, length-4, ENC_NA);
820 return length-4-16;
822 return length-4;
826 /* 5.1.2 Service Info Component */
828 #define SERVICE_INFO_LEN (4+4+8*2)
830 #define WCCP2_SERVICE_STANDARD 0
831 #define WCCP2_SERVICE_DYNAMIC 1
833 static const value_string service_type_vals[] = {
834 { WCCP2_SERVICE_STANDARD, "Standard predefined service"},
835 { WCCP2_SERVICE_DYNAMIC, "Dynamic CE defined service" },
836 { 0, NULL }
840 * Service flags.
842 #define WCCP2_SI_SRC_IP_HASH 0x00000001
843 #define WCCP2_SI_DST_IP_HASH 0x00000002
844 #define WCCP2_SI_SRC_PORT_HASH 0x00000004
845 #define WCCP2_SI_DST_PORT_HASH 0x00000008
846 #define WCCP2_SI_PORTS_DEFINED 0x00000010
847 #define WCCP2_SI_PORTS_SOURCE 0x00000020
848 #define WCCP2r1_SI_REDIRECT_ONLY_PROTOCOL_0 0x00000040
849 #define WCCP2_SI_SRC_IP_ALT_HASH 0x00000100
850 #define WCCP2_SI_DST_IP_ALT_HASH 0x00000200
851 #define WCCP2_SI_SRC_PORT_ALT_HASH 0x00000400
852 #define WCCP2_SI_DST_PORT_ALT_HASH 0x00000800
855 static int
856 dissect_wccp2_service_info(tvbuff_t *tvb, int offset, int length,
857 packet_info *pinfo, proto_tree *info_tree, wccp_address_table* addr_table _U_)
859 uint8_t service_type;
860 uint32_t flags;
861 proto_item *tf;
862 proto_tree *ports_tree;
863 int i;
864 int max_offset = offset+length;
866 static int * const flag_fields[] = {
867 &hf_service_info_flags_src_ip_hash,
868 &hf_service_info_flags_dest_ip_hash,
869 &hf_service_info_flags_src_port_hash,
870 &hf_service_info_flags_dest_port_hash,
871 &hf_service_info_flags_ports_defined,
872 &hf_service_info_flags_ports_source,
873 &hf_service_info_flags_redirect_only_protocol_0,
874 &hf_service_info_flags_src_ip_alt_hash,
875 &hf_service_info_flags_dest_ip_alt_hash,
876 &hf_service_info_flags_src_port_alt_hash,
877 &hf_service_info_flags_dest_port_alt_hash,
878 &hf_service_info_flags_reserved,
879 NULL
882 if (length != SERVICE_INFO_LEN)
883 return length - SERVICE_INFO_LEN;
885 service_type = tvb_get_uint8(tvb, offset);
886 proto_tree_add_item(info_tree, hf_service_info_type, tvb,
887 offset, 1, ENC_BIG_ENDIAN);
889 switch (service_type) {
891 case WCCP2_SERVICE_STANDARD:
892 proto_tree_add_item(info_tree, hf_service_info_id_standard, tvb,
893 offset +1 , 1, ENC_BIG_ENDIAN);
895 tf = proto_tree_add_item(info_tree, hf_service_info_priority, tvb, offset+2, 1, ENC_BIG_ENDIAN);
896 if (tvb_get_uint8(tvb, offset+2) != 0)
897 expert_add_info(pinfo, tf, &ei_wccp_service_info_priority_nonzero);
899 tf = proto_tree_add_item(info_tree, hf_service_info_protocol, tvb,
900 offset+3, 1, ENC_BIG_ENDIAN);
902 if (tvb_get_uint8(tvb, offset+3) != 0)
903 expert_add_info(pinfo, tf, &ei_wccp_service_info_protocol_nonzero);
904 break;
906 case WCCP2_SERVICE_DYNAMIC:
907 proto_tree_add_item(info_tree, hf_service_info_id_dynamic, tvb,
908 offset +1 , 1, ENC_BIG_ENDIAN);
909 proto_tree_add_item(info_tree, hf_service_info_priority, tvb,
910 offset+2, 1, ENC_BIG_ENDIAN);
911 proto_tree_add_item(info_tree, hf_service_info_protocol, tvb,
912 offset+3, 1, ENC_BIG_ENDIAN);
913 break;
915 offset += 4;
917 flags = tvb_get_ntohl(tvb, offset);
918 proto_tree_add_bitmask(info_tree, tvb, offset, hf_service_info_flags, ett_service_flags, flag_fields, ENC_BIG_ENDIAN);
920 offset += 4;
922 if (flags & WCCP2_SI_PORTS_DEFINED) {
923 ports_tree = proto_tree_add_subtree(info_tree, tvb, offset, 2*8,
924 ett_service_info_ports, &tf, "Ports list: ");
926 for (i = 0; i < 8; i++) {
927 uint16_t port = tvb_get_ntohs(tvb, offset);
929 if (port) {
930 if (flags & WCCP2_SI_SRC_PORT_HASH)
931 proto_tree_add_item(ports_tree, hf_service_info_source_port, tvb, offset, 2, ENC_BIG_ENDIAN);
932 else
933 proto_tree_add_item(ports_tree, hf_service_info_destination_port, tvb, offset, 2, ENC_BIG_ENDIAN);
934 proto_item_append_text(tf, " %d", port);
936 offset += 2;
937 DISSECTOR_ASSERT(offset <= max_offset);
940 else {
941 /* just use up the space if there is */
942 if (offset + 8 * 2 <= max_offset) {
943 proto_tree_add_expert(info_tree, pinfo, &ei_wccp_port_fields_not_used, tvb, offset, 8*2);
944 /*offset += 8*2;*/
948 return length - SERVICE_INFO_LEN;
951 /* 6.1 Router Identity Element */
952 static void
953 dissect_wccp2_router_identity_element(tvbuff_t *tvb, int offset, packet_info *pinfo,
954 proto_tree *tree, wccp_address_table* addr_table)
956 proto_item *tf;
959 wccp_add_ipaddress_item(tree, hf_router_identity_ip_index, hf_router_identity_ipv4, hf_router_identity_ipv6, tvb, offset, 4, addr_table);
960 tf = proto_tree_add_item(tree, hf_router_identity_receive_id, tvb, offset+4, 4, ENC_BIG_ENDIAN);
962 if (tvb_get_ntohl(tvb, offset + 4) == 0)
963 expert_add_info(pinfo, tf, &ei_wccp_router_identity_receive_id_zero);
966 #define ROUTER_ID_INFO_MIN_LEN (8+4+4)
968 /* 5.3.1 Router Identity Info Component */
969 static int
970 dissect_wccp2_router_identity_info(tvbuff_t *tvb, int offset, int length,
971 packet_info *pinfo, proto_tree *info_tree, wccp_address_table* addr_table)
973 uint32_t n_received_from;
974 unsigned i;
975 proto_item *te;
976 proto_tree *element_tree;
978 if (length < 8)
979 return length - ROUTER_ID_INFO_MIN_LEN;
982 te = wccp_add_ipaddress_item(info_tree, hf_router_identity_router_ip_index, hf_router_identity_router_ipv4, hf_router_identity_router_ipv6, tvb, offset, 4, addr_table);
984 element_tree = proto_item_add_subtree(te,ett_wc_view_info_router_element);
986 dissect_wccp2_router_identity_element(tvb,offset,pinfo,element_tree, addr_table);
987 EAT_AND_CHECK(8,4);
989 wccp_add_ipaddress_item(info_tree, hf_router_identity_send_to_ip_index, hf_router_identity_send_to_ipv4, hf_router_identity_send_to_ipv6, tvb, offset, 4, addr_table);
990 EAT_AND_CHECK(4,4);
992 n_received_from = tvb_get_ntohl(tvb, offset);
993 proto_tree_add_item(info_tree, hf_router_identity_received_from_num, tvb, offset, 4, ENC_BIG_ENDIAN);
994 EAT(4);
996 for (i = 0; i < n_received_from; i++) {
997 if (length < 4)
998 return length-4*(i-n_received_from);
1001 wccp_add_ipaddress_item(info_tree, hf_router_identity_received_from_ip_index, hf_router_identity_received_from_ipv4, hf_router_identity_received_from_ipv6, tvb, offset, 4, addr_table);
1002 EAT(4);
1005 return length;
1008 #define ROUTER_WC_ID_ELEMENT_MIN_LEN (4+2+2)
1010 /* 6.4 Web-Cache Identity Element */
1011 static int
1012 dissect_wccp2_web_cache_identity_element(tvbuff_t *tvb, int offset, int length, packet_info *pinfo,
1013 proto_tree *info_tree, wccp_address_table* addr_table)
1015 proto_item *tf;
1016 uint16_t flags;
1017 unsigned data_element_type;
1019 static int * const flag_fields[] = {
1020 &hf_web_cache_identity_flag_hash_info,
1021 &hf_web_cache_identity_flag_assign_type,
1022 &hf_web_cache_identity_flag_version_request,
1023 &hf_web_cache_identity_flag_reserved,
1024 NULL
1027 if (length < ROUTER_WC_ID_ELEMENT_MIN_LEN)
1028 return length - ROUTER_WC_ID_ELEMENT_MIN_LEN;
1030 wccp_add_ipaddress_item(info_tree, hf_web_cache_identity_index, hf_web_cache_identity_ipv4, hf_web_cache_identity_ipv6, tvb, offset, 4, addr_table);
1031 EAT_AND_CHECK(4,2);
1033 tf = proto_tree_add_item(info_tree, hf_web_cache_identity_hash_rev, tvb, offset, 2, ENC_BIG_ENDIAN);
1034 if (tvb_get_ntohs(tvb, offset) != 0)
1035 expert_add_info(pinfo, tf, &ei_wccp_web_cache_identity_hash_rev_zero);
1037 EAT_AND_CHECK(2,2);
1039 flags = tvb_get_ntohs(tvb, offset);
1040 data_element_type = (flags & 0x6) >> 1;
1041 proto_tree_add_bitmask(info_tree, tvb, offset, hf_web_cache_identity_flags, ett_wc_identity_flags, flag_fields, ENC_BIG_ENDIAN);
1043 EAT(2);
1045 switch (data_element_type) {
1046 case WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_HASH:
1047 return dissect_wccp2_hash_assignment_data_element(tvb,offset,length,pinfo,info_tree);
1048 case WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_MASK:
1049 return dissect_wccp2_mask_assignment_data_element(tvb,offset,length,pinfo,info_tree, addr_table);
1051 case WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_NOT_PRESENT:
1052 proto_tree_add_item(info_tree, hf_assignment_no_data, tvb, offset, 2, ENC_NA);
1053 return length;
1054 case WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_EXTENDED:
1055 return dissect_wccp2_extended_assignment_data_element(tvb,offset,length,pinfo,info_tree, addr_table);
1057 return length;
1060 /* 5.2.1 Web-Cache Identity Info Component */
1061 static int
1062 dissect_wccp2_wc_identity_info(tvbuff_t *tvb, int offset, int length,
1063 packet_info *pinfo _U_, proto_tree *info_tree, wccp_address_table* addr_table)
1065 proto_item *te;
1066 proto_tree *element_tree;
1068 te = wccp_add_ipaddress_item(info_tree, hf_wc_identity_ip_address_index, hf_wc_identity_ip_address_ipv4, hf_wc_identity_ip_address_ipv6,
1069 tvb, offset, 4, addr_table);
1071 element_tree = proto_item_add_subtree(te, ett_wc_identity_element);
1072 return dissect_wccp2_web_cache_identity_element(tvb, offset,length, pinfo,
1073 element_tree, addr_table);
1076 /* 6.3 Assignment Key Element */
1077 static int
1078 dissect_wccp2_assignment_key_element(tvbuff_t *tvb, int offset, int length, packet_info *pinfo _U_,
1079 proto_tree *info_tree, wccp_address_table* addr_table)
1081 if (length < 8)
1082 return length -8;
1085 wccp_add_ipaddress_item(info_tree, hf_assignment_key_ip_index, hf_assignment_key_ipv4, hf_assignment_key_ipv6, tvb, offset, 4, addr_table);
1087 EAT_AND_CHECK(4,4);
1088 proto_tree_add_item(info_tree, hf_assignment_key_change_num, tvb, offset, 4, ENC_BIG_ENDIAN);
1089 EAT(4);
1091 return length;
1095 #define ROUTER_VIEW_INFO_MIN_LEN (4+8+4+4)
1097 /* 5.3.2 Router View Info Component */
1098 static int
1099 dissect_wccp2_router_view_info(tvbuff_t *tvb, int offset, int length,
1100 packet_info *pinfo, proto_tree *info_tree, wccp_address_table* addr_table)
1102 uint32_t n_routers;
1103 uint32_t n_web_caches;
1104 unsigned i;
1105 proto_item *te;
1106 proto_tree *element_tree;
1107 int new_length;
1109 if (length < ROUTER_VIEW_INFO_MIN_LEN)
1110 return length - ROUTER_VIEW_INFO_MIN_LEN;
1112 proto_tree_add_item(info_tree, hf_router_view_member_change_num, tvb, offset, 4, ENC_BIG_ENDIAN);
1113 EAT(4);
1115 new_length=dissect_wccp2_assignment_key_element(tvb, offset, length, pinfo, info_tree, addr_table);
1116 CHECK_LENGTH_ADVANCE_OFFSET(new_length);
1118 n_routers = tvb_get_ntohl(tvb, offset);
1119 proto_tree_add_uint(info_tree, hf_router_router_num, tvb, offset, 4, n_routers);
1120 EAT(4);
1122 for (i = 0; i < n_routers; i++) {
1123 if (length < 4)
1124 return length - (n_routers-i)*4 - 4;
1126 wccp_add_ipaddress_item(info_tree, hf_router_view_ip_index, hf_router_view_ipv4, hf_router_view_ipv6, tvb, offset, 4, addr_table);
1127 EAT(4);
1130 if (length < 4)
1131 return length - 4;
1133 n_web_caches = tvb_get_ntohl(tvb, offset);
1134 proto_tree_add_uint(info_tree, hf_wc_view_wc_num, tvb, offset, 4, n_web_caches);
1135 EAT(4);
1137 for (i = 0; i < n_web_caches; i++) {
1138 int old_length;
1139 old_length = length;
1141 if (length < 4)
1142 return length - 4*(n_web_caches-i);
1144 te = wccp_add_ipaddress_item(info_tree, hf_router_query_info_ip_index, hf_router_query_info_ipv4, hf_router_query_info_ipv6, tvb, offset, 4, addr_table);
1146 element_tree = proto_item_add_subtree(te, ett_wc_identity_element);
1147 length = dissect_wccp2_web_cache_identity_element(tvb,
1148 offset, length, pinfo,
1149 element_tree, addr_table);
1150 if (length < 0)
1151 return length;
1153 offset += old_length - length;
1155 return length;
1158 #define WC_VIEW_INFO_MIN_LEN (4+4+4)
1160 /* 5.2.2 Web Cache View Info Component */
1162 static int
1163 dissect_wccp2_web_cache_view_info(tvbuff_t *tvb, int offset, int length,
1164 packet_info *pinfo, proto_tree *info_tree, wccp_address_table* addr_table)
1166 uint32_t n_routers;
1167 uint32_t n_web_caches;
1168 unsigned i;
1169 proto_item *te;
1170 proto_tree *element_tree;
1173 if (length < WC_VIEW_INFO_MIN_LEN)
1174 return length - WC_VIEW_INFO_MIN_LEN;
1177 proto_tree_add_item(info_tree, hf_wc_view_info_change_num, tvb, offset, 4, ENC_BIG_ENDIAN);
1178 EAT_AND_CHECK(4,4);
1180 n_routers = tvb_get_ntohl(tvb, offset);
1181 proto_tree_add_uint(info_tree, hf_wc_view_router_num, tvb, offset, 4, n_routers);
1182 EAT(4);
1184 for (i = 0; i < n_routers; i++) {
1185 if (length < 8)
1186 return length -8 * (n_routers-i) - 4;
1188 te = wccp_add_ipaddress_item(info_tree, hf_wc_view_info_router_ip_index, hf_wc_view_info_router_ipv4, hf_wc_view_info_router_ipv6, tvb, offset, 4, addr_table);
1189 /* also include the receive id in the object */
1190 proto_item_set_len(te, 8);
1192 element_tree = proto_item_add_subtree(te,ett_wc_view_info_router_element);
1193 dissect_wccp2_router_identity_element(tvb, offset, pinfo, element_tree, addr_table);
1194 EAT(8);
1197 if (length < 4)
1198 return length - 4;
1200 n_web_caches = tvb_get_ntohl(tvb, offset);
1201 proto_tree_add_uint(info_tree, hf_wc_view_wc_num, tvb, offset, 4, n_web_caches);
1202 EAT(4);
1204 for (i = 0; i < n_web_caches; i++) {
1205 if (length < 4)
1206 return length - 4*(n_web_caches-i);
1208 wccp_add_ipaddress_item(info_tree, hf_wc_view_info_wc_ip_index, hf_wc_view_info_wc_ipv4, hf_wc_view_info_wc_ipv6, tvb, offset, 4, addr_table);
1209 EAT(4);
1211 return length;
1214 /* 6.2 Router Assignment Element */
1215 static void
1216 dissect_wccp2_router_assignment_element(tvbuff_t *tvb, int offset,
1217 int length _U_, packet_info *pinfo, proto_tree *info_tree, wccp_address_table* addr_table)
1219 dissect_wccp2_router_identity_element(tvb,offset,pinfo,info_tree, addr_table);
1220 EAT(8);
1221 proto_tree_add_item(info_tree, hf_router_assignment_element_change_num, tvb, offset, 4, ENC_BIG_ENDIAN);
1222 EAT(4);
1225 static const char *
1226 assignment_bucket_name(uint8_t bucket)
1228 const char *cur;
1230 if (bucket == 0xff) {
1231 cur= "Unassigned";
1232 } else {
1233 cur=wmem_strdup_printf(wmem_packet_scope(), "%u%s", bucket & 0x7F,
1234 (bucket & 0x80) ? " (Alt)" : "");
1236 return cur;
1239 #define ASSIGNMENT_INFO_MIN_LEN (8+4+4)
1241 /* 5.4.1 Assignment Info Component */
1242 static int
1243 dissect_wccp2_assignment_info(tvbuff_t *tvb, int offset, int length,
1244 packet_info *pinfo, proto_tree *info_tree, wccp_address_table* addr_table)
1246 uint32_t n_routers;
1247 unsigned i;
1248 proto_item *te;
1249 proto_tree *element_tree;
1250 int new_length;
1252 if (length < ASSIGNMENT_INFO_MIN_LEN)
1253 return length - ASSIGNMENT_INFO_MIN_LEN;
1256 new_length=dissect_wccp2_assignment_key_element(tvb, offset, length, pinfo, info_tree, addr_table);
1257 CHECK_LENGTH_ADVANCE_OFFSET(new_length);
1259 n_routers = tvb_get_ntohl(tvb, offset);
1260 proto_tree_add_uint(info_tree, hf_assignment_info_router_num, tvb, offset, 4, n_routers);
1261 EAT(4);
1263 for (i = 0; i < n_routers; i++) {
1264 if (length < 12)
1265 return length - 12*(n_routers-i)-4-256;
1267 te = wccp_add_ipaddress_item(info_tree, hf_assignment_info_router_ip_index, hf_assignment_info_router_ipv4, hf_assignment_info_router_ipv6, tvb, offset, 4, addr_table);
1269 element_tree = proto_item_add_subtree(te, ett_router_assignment_element);
1270 dissect_wccp2_router_assignment_element(tvb, offset, length , pinfo,
1271 element_tree, addr_table);
1272 EAT(12);
1275 new_length = dissect_wccp2_hash_buckets_assignment_element(tvb, offset, length, pinfo, info_tree, addr_table);
1276 CHECK_LENGTH_ADVANCE_OFFSET(new_length);
1277 return length;
1281 #define QUERY_INFO_LEN (4+4+4+4)
1283 /* 5.5.1 Router Query Info Component */
1284 static int
1285 dissect_wccp2_router_query_info(tvbuff_t *tvb, int offset, int length,
1286 packet_info *pinfo, proto_tree *info_tree, wccp_address_table* addr_table)
1288 if (length < QUERY_INFO_LEN)
1289 return length - QUERY_INFO_LEN;
1291 dissect_wccp2_router_identity_element(tvb,offset,pinfo,info_tree, addr_table);
1292 EAT_AND_CHECK(8,4);
1294 wccp_add_ipaddress_item(info_tree, hf_router_query_info_send_to_ip_index, hf_router_query_info_send_to_ipv4, hf_router_query_info_send_to_ipv6, tvb, offset, 4, addr_table);
1295 EAT_AND_CHECK(4,4);
1296 wccp_add_ipaddress_item(info_tree, hf_router_query_info_target_ip_index, hf_router_query_info_target_ipv4, hf_router_query_info_target_ipv6, tvb, offset, 4, addr_table);
1297 EAT(4);
1299 return length;
1302 /* 6.5 Hash Buckets Assignment Element */
1303 static int dissect_wccp2_hash_buckets_assignment_element(tvbuff_t *tvb, int offset, int length,
1304 packet_info *pinfo _U_, proto_tree *info_tree, wccp_address_table* addr_table)
1306 uint32_t i,n_web_caches;
1307 proto_item *te;
1308 proto_tree *element_tree;
1309 uint8_t bucket;
1311 if (length < 4)
1312 return length - 4;
1314 te = proto_tree_add_item_ret_uint(info_tree, hf_hash_buckets_assignment_wc_num, tvb, offset, 4, ENC_BIG_ENDIAN, &n_web_caches);
1315 EAT(4);
1317 element_tree = proto_item_add_subtree(te,ett_hash_buckets_assignment_wc_element);
1318 for (i = 0; i < n_web_caches; i++) {
1319 proto_item *l_te;
1321 if (length < 4)
1322 return length - 4*(n_web_caches-i)-256;
1324 l_te = wccp_add_ipaddress_item(element_tree, hf_hash_buckets_assignment_wc_ip_index, hf_hash_buckets_assignment_wc_ipv4, hf_hash_buckets_assignment_wc_ipv6, tvb, offset, 4, addr_table);
1326 proto_item_append_text(l_te, " id: %d", i);
1327 EAT(4);
1330 element_tree = proto_tree_add_subtree(info_tree,tvb, offset, 256, ett_hash_buckets_assignment_buckets, NULL, "Buckets");
1332 for (i = 0; i < 256; i++, offset++, length--) {
1333 if (length < 1)
1334 return length - (256-i);
1335 bucket = tvb_get_uint8(tvb, offset);
1336 proto_tree_add_uint_format(element_tree, hf_bucket, tvb, offset, 1,
1337 bucket, "Bucket %3d: %10s",
1338 i, assignment_bucket_name(bucket));
1340 return length;
1343 #define WCCP2_FORWARDING_METHOD_GRE 0x00000001
1344 #define WCCP2_FORWARDING_METHOD_L2 0x00000002
1346 static const capability_flag forwarding_method_flags[] = {
1347 { WCCP2_FORWARDING_METHOD_GRE, "IP-GRE", &hf_capability_forwarding_method_flag_gre },
1348 { WCCP2_FORWARDING_METHOD_L2, "L2", &hf_capability_forwarding_method_flag_l2 },
1349 { 0, NULL, NULL }
1352 #define WCCP2_ASSIGNMENT_METHOD_HASH 0x00000001
1353 #define WCCP2_ASSIGNMENT_METHOD_MASK 0x00000002
1355 static const capability_flag assignment_method_flags[] = {
1356 { WCCP2_ASSIGNMENT_METHOD_HASH, "Hash", &hf_capability_assignment_method_flag_hash },
1357 { WCCP2_ASSIGNMENT_METHOD_MASK, "Mask", &hf_capability_assignment_method_flag_mask },
1358 { 0, NULL, NULL }
1362 #define WCCP2_PACKET_RETURN_METHOD_GRE 0x00000001
1363 #define WCCP2_PACKET_RETURN_METHOD_L2 0x00000002
1365 static const capability_flag packet_return_method_flags[] = {
1366 { WCCP2_PACKET_RETURN_METHOD_GRE, "IP-GRE", &hf_capability_return_method_flag_gre },
1367 { WCCP2_PACKET_RETURN_METHOD_L2, "L2", &hf_capability_return_method_flag_l2 },
1368 { 0, NULL, NULL }
1371 #define WCCP2_COMMAND_TYPE_SHUTDOWN 1
1372 #define WCCP2_COMMAND_TYPE_SHUTDOWN_RESPONSE 2
1374 static const value_string wccp_command_type_vals[] = {
1375 { WCCP2_COMMAND_TYPE_SHUTDOWN, "CE shutting down" },
1376 { WCCP2_COMMAND_TYPE_SHUTDOWN_RESPONSE, "Router Acknowledge CE shutdown"},
1377 { 0, NULL }
1382 /* 5.1.3 Capabilities Info Component */
1384 static int
1385 dissect_wccp2_capability_info(tvbuff_t *tvb, int offset, int length,
1386 packet_info *pinfo, proto_tree *info_tree, wccp_address_table* addr_table _U_)
1388 int capability_length;
1390 while (length >= 8) {
1391 capability_length = dissect_wccp2_capability_element(tvb,offset,length,pinfo,info_tree);
1393 CHECK_LENGTH_ADVANCE_OFFSET(capability_length);
1395 return length;
1399 #define ALT_COMMAND_EXTENSION_MIN_LEN (4)
1401 /* 5.1.4 && 6.12 Command Extension Component */
1403 static int
1404 dissect_wccp2_command_extension(tvbuff_t *tvb, int offset,
1405 int length, packet_info *pinfo _U_, proto_tree *info_tree, wccp_address_table* addr_table)
1407 uint16_t command_type;
1408 uint32_t command_length;
1410 for (;;) {
1411 if (length == 0)
1412 return length;
1414 if (length < ALT_COMMAND_EXTENSION_MIN_LEN )
1415 return length - ALT_COMMAND_EXTENSION_MIN_LEN ;
1417 command_type = tvb_get_ntohs(tvb, offset);
1418 proto_tree_add_item(info_tree, hf_command_element_type, tvb, offset, 2, ENC_BIG_ENDIAN);
1419 EAT_AND_CHECK(2,2);
1421 proto_tree_add_item_ret_uint(info_tree, hf_command_element_length, tvb, offset, 2, ENC_BIG_ENDIAN, &command_length);
1422 proto_tree_add_item(info_tree, hf_command_length, tvb, offset, 2, ENC_BIG_ENDIAN);
1423 EAT(2);
1425 if (((command_type == WCCP2_COMMAND_TYPE_SHUTDOWN) ||
1426 (command_type == WCCP2_COMMAND_TYPE_SHUTDOWN_RESPONSE)) &&
1427 (command_length == 4)) {
1428 if (length < 4)
1429 return length - 4;
1431 wccp_add_ipaddress_item(info_tree, hf_command_element_shutdown_ip_index, hf_command_element_shutdown_ipv4, hf_command_element_shutdown_ipv6, tvb, offset, 4, addr_table);
1432 } else {
1433 if (length < (int)command_length)
1434 return length - command_length;
1436 proto_tree_add_item(info_tree, hf_command_unknown, tvb, offset, command_length, ENC_NA);
1438 EAT(command_length);
1443 /* 5.1.5 Address Table Component */
1444 /* this function is special as it can be invoked twice during a packet decode:
1445 once to get the tables, once to display them
1447 static int
1448 dissect_wccp2r1_address_table_info(tvbuff_t *tvb, int offset, int length,
1449 packet_info *pinfo, proto_tree *info_tree, wccp_address_table* wccp_wccp_address_table)
1451 uint16_t address_length;
1452 uint32_t i;
1453 int16_t family;
1454 uint16_t table_length;
1455 proto_tree *element_tree;
1456 proto_item *tf;
1458 if (length < 2*4)
1459 return length - 2*4;
1461 family = tvb_get_ntohs(tvb, offset);
1462 proto_tree_add_item(info_tree, hf_address_table_family, tvb, offset, 2, ENC_BIG_ENDIAN);
1463 EAT_AND_CHECK(2,2);
1465 address_length = tvb_get_ntohs(tvb, offset);
1466 proto_tree_add_item(info_tree, hf_address_table_address_length, tvb, offset, 2, ENC_BIG_ENDIAN);
1467 EAT_AND_CHECK(2,2);
1469 table_length = tvb_get_ntohl(tvb, offset);
1470 tf = proto_tree_add_item(info_tree, hf_address_table_length, tvb, offset, 4, ENC_BIG_ENDIAN);
1471 element_tree = proto_item_add_subtree(tf, ett_table_element);
1472 EAT(4);
1474 if (wccp_wccp_address_table->in_use == false) {
1475 wccp_wccp_address_table->family = family;
1476 wccp_wccp_address_table->table_length = table_length;
1478 /* check if the length is valid and allocate the tables if needed */
1479 switch (wccp_wccp_address_table->family) {
1480 case 1:
1481 if (wccp_wccp_address_table->table_ipv4 == NULL)
1482 wccp_wccp_address_table->table_ipv4 = (uint32_t *)
1483 wmem_alloc0(pinfo->pool, wccp_wccp_address_table->table_length * 4);
1484 if (address_length != 4) {
1485 expert_add_info_format(pinfo, tf, &ei_wccp_length_bad,
1486 "The Address length must be 4, but I found %d for IPv4 addresses. Correcting this.",
1487 address_length);
1488 address_length = 4;
1490 break;
1491 case 2:
1492 if (wccp_wccp_address_table->table_ipv6 == NULL)
1493 wccp_wccp_address_table->table_ipv6 = (ws_in6_addr *)
1494 wmem_alloc0(pinfo->pool, wccp_wccp_address_table->table_length * sizeof(ws_in6_addr));
1495 if (address_length != 16) {
1496 expert_add_info_format(pinfo, tf, &ei_wccp_length_bad,
1497 "The Address length must be 16, but I found %d for IPv6 addresses. Correcting this.",
1498 address_length);
1499 address_length = 16;
1501 break;
1502 default:
1503 expert_add_info_format(pinfo, tf, &ei_wccp_address_table_family_unknown,
1504 "Unknown address family: %d", wccp_wccp_address_table->family);
1508 /* now read the addresses and print/store them */
1510 for(i=0; i<table_length; i++) {
1511 const char *addr;
1513 switch (family) {
1514 case 1:
1515 /* IPv4 */
1516 addr = tvb_ip_to_str(pinfo->pool, tvb, offset);
1517 if ((wccp_wccp_address_table->in_use == false) &&
1518 (wccp_wccp_address_table->table_ipv4 != NULL) &&
1519 (i < wccp_wccp_address_table->table_length))
1520 wccp_wccp_address_table->table_ipv4[i] = tvb_get_ipv4(tvb, offset);
1521 break;
1522 case 2:
1523 /* IPv6 */
1524 addr = tvb_ip6_to_str(pinfo->pool, tvb, offset);
1525 if ((wccp_wccp_address_table->in_use == false) &&
1526 (wccp_wccp_address_table->table_ipv6 != NULL) &&
1527 (i < wccp_wccp_address_table->table_length))
1528 tvb_get_ipv6(tvb, offset, &(wccp_wccp_address_table->table_ipv6[i]));
1529 break;
1530 default:
1531 addr = wmem_strdup_printf(wmem_packet_scope(), "unknown family %d", wccp_wccp_address_table->family);
1534 if (element_tree) {
1535 proto_item *pi;
1537 pi = proto_tree_add_string_format_value(element_tree, hf_address_table_element, tvb,
1538 offset, address_length, addr,
1539 "%d: %s", i+1, addr);
1540 if (i > wccp_wccp_address_table->table_length)
1541 expert_add_info_format(pinfo, pi, &ei_wccp_length_bad, "Ran out of space to store address");
1543 EAT(address_length);
1546 wccp_wccp_address_table->in_use = true;
1547 return length;
1554 #define HASH_ASSIGNMENT_INFO_MIN_LEN (4+256)
1556 /* part of 5.6.11 Alternate Assignment Component */
1557 static int
1558 dissect_wccp2_hash_assignment_info(tvbuff_t *tvb, int offset, int length,
1559 packet_info *pinfo, proto_tree *info_tree, wccp_address_table* addr_table)
1561 uint32_t n_web_caches, host_addr;
1562 unsigned i;
1563 uint8_t bucket;
1565 if (length < HASH_ASSIGNMENT_INFO_MIN_LEN)
1566 return length - ASSIGNMENT_INFO_MIN_LEN;
1568 proto_tree_add_item_ret_uint(info_tree, hf_wc_view_wc_num, tvb, offset, 4, ENC_BIG_ENDIAN, &n_web_caches);
1569 EAT(4);
1571 for (i = 0; i < n_web_caches; i++) {
1572 if (length < 4)
1573 return length - 4*(n_web_caches-i)-256;
1575 host_addr = tvb_get_ntohl(tvb,offset);
1576 if (! addr_table->in_use){
1577 proto_tree_add_ipv4_format(info_tree, hf_cache_ip, tvb, offset, 4, host_addr, "Web-Cache %d: IP address %s", i,
1578 decode_wccp_encoded_address(tvb, offset, pinfo, info_tree, addr_table));
1579 } else {
1580 proto_tree_add_uint_format(info_tree, hf_web_cache_identity_index, tvb, offset, 4, host_addr, "Web-Cache %d: IP address %s", i,
1581 decode_wccp_encoded_address(tvb, offset, pinfo, info_tree, addr_table));
1583 EAT(4);
1587 for (i = 0; i < 256; i++, offset++, length--) {
1588 if (length < 1)
1589 return length - (256-i);
1590 bucket = tvb_get_uint8(tvb, offset);
1591 proto_tree_add_uint_format(info_tree, hf_bucket, tvb, offset, 1,
1592 bucket, "Bucket %3d: %10s",
1593 i, assignment_bucket_name(bucket));
1595 return length;
1598 /* 5.3.3 Assignment Map Component */
1599 static int dissect_wccp2_assignment_map(tvbuff_t *tvb, int offset,
1600 int length, packet_info *pinfo, proto_tree *info_tree, wccp_address_table* addr_table)
1602 int new_length;
1604 new_length=dissect_wccp2_mask_value_set_list(tvb, offset, length, pinfo, info_tree, addr_table);
1606 CHECK_LENGTH_ADVANCE_OFFSET(new_length);
1608 return length;
1613 #define ALT_ASSIGNMENT_MAP_MIN_LEN (4)
1615 /* 5.3.4 Alternate Assignment Map Component */
1616 static int
1617 dissect_wccp2r1_alt_assignment_map_info(tvbuff_t *tvb, int offset,
1618 int length, packet_info *pinfo, proto_tree *info_tree, wccp_address_table* addr_table)
1620 uint16_t assignment_type;
1621 uint16_t assignment_length;
1622 proto_item *tf=NULL;
1624 if (length < ALT_ASSIGNMENT_MAP_MIN_LEN )
1625 return length - ALT_ASSIGNMENT_MAP_MIN_LEN ;
1628 assignment_type = tvb_get_ntohs(tvb, offset);
1629 proto_tree_add_item(info_tree, hf_alt_assignment_map_assignment_type, tvb, offset, 2, ENC_BIG_ENDIAN);
1630 EAT_AND_CHECK(2,2);
1632 assignment_length = tvb_get_ntohs(tvb, offset);
1633 tf=proto_tree_add_item(info_tree, hf_alt_assignment_map_assignment_length, tvb, offset, 2, ENC_BIG_ENDIAN);
1634 EAT(2);
1636 if (length < assignment_length)
1637 expert_add_info_format(pinfo, tf, &ei_wccp_assignment_length_bad,
1638 "Assignment length is %d but only %d remain in the packet. Ignoring this for now",
1639 assignment_length, length);
1641 if (length > assignment_length) {
1642 expert_add_info_format(pinfo, tf, &ei_wccp_assignment_length_bad,
1643 "Assignment length is %d but %d remain in the packet. Assuming that the assignment length is wrong and setting it to %d.",
1644 assignment_length, length, length);
1645 assignment_length = length;
1648 switch (assignment_type) {
1649 case WCCP2_HASH_ASSIGNMENT_TYPE:
1650 return dissect_wccp2_assignment_info(tvb, offset, assignment_length,
1651 pinfo, info_tree, addr_table);
1652 case WCCP2_MASK_ASSIGNMENT_TYPE:
1653 return dissect_wccp2_mask_value_set_list(tvb, offset, assignment_length,
1654 pinfo, info_tree, addr_table);
1655 case WCCP2r1_ALT_MASK_ASSIGNMENT_TYPE:
1656 return dissect_wccp2_alternate_mask_value_set_list(tvb, offset, assignment_length,
1657 pinfo, info_tree, addr_table);
1658 default:
1659 return length;
1667 /* 6.6 Hash Assignment Data Element */
1668 static int
1669 dissect_wccp2_hash_assignment_data_element(tvbuff_t *tvb, int offset, int length,
1670 packet_info *pinfo _U_,
1671 proto_tree *info_tree)
1674 proto_tree *bucket_tree;
1675 int i;
1676 uint8_t bucket_info;
1677 int n;
1680 bucket_tree = proto_tree_add_subtree(info_tree, tvb, offset, 8*4,
1681 ett_hash_assignment_buckets, NULL, "Hash Assignment Data");
1683 for (i = 0, n = 0; i < 32; i++) {
1684 if (length == 0) {
1685 return -i-2-2;
1688 bucket_info = tvb_get_uint8(tvb, offset);
1689 n = wccp_bucket_info(bucket_info, bucket_tree, n, tvb, offset);
1690 EAT(1);
1693 if (length < 2){
1694 return -2-2;
1697 return dissect_wccp2_assignment_weight_and_status_element(tvb, offset, length, pinfo, info_tree);
1700 /* 6.7 Mask Assignment Data Element */
1701 static int
1702 dissect_wccp2_mask_assignment_data_element(tvbuff_t *tvb, int offset, int length, packet_info *pinfo,
1703 proto_tree *info_tree, wccp_address_table* addr_table)
1706 proto_item *mask_item;
1707 proto_tree *mask_tree;
1708 int new_length,start;
1711 mask_tree = proto_tree_add_subtree(info_tree, tvb, offset, 4,
1712 ett_mask_assignment_data_element, &mask_item, "Mask Assignment Data");
1713 start = offset;
1715 new_length=dissect_wccp2_mask_value_set_list(tvb, offset, length, pinfo, mask_tree, addr_table);
1717 CHECK_LENGTH_ADVANCE_OFFSET(new_length);
1719 if (length < 2)
1720 return length-4;
1722 new_length = dissect_wccp2_assignment_weight_and_status_element(tvb, offset, length, pinfo, info_tree);
1723 CHECK_LENGTH_ADVANCE_OFFSET(new_length);
1725 proto_item_set_len(mask_item, offset-start);
1726 return length;
1730 /* 5.7.5 Alternate Mask Assignment Data Element */
1731 static int
1732 dissect_wccp2_alternate_mask_assignment_data_element(tvbuff_t *tvb, int offset, int length, packet_info *pinfo,
1733 proto_tree *info_tree, wccp_address_table* addr_table)
1735 proto_tree *mask_tree;
1737 mask_tree = proto_tree_add_subtree(info_tree, tvb, offset, length,
1738 ett_alternate_mask_assignment_data_element, NULL, "Alternate Mask Assignment Data");
1740 if (length < 4)
1741 return length-4;
1743 if (length > 4)
1744 for (;length >4;)
1746 int new_length;
1748 new_length=dissect_wccp2_alternate_mask_value_set_list(tvb, offset, length, pinfo, mask_tree, addr_table);
1750 CHECK_LENGTH_ADVANCE_OFFSET(new_length);
1753 if (length < 2)
1754 return -2;
1756 return dissect_wccp2_assignment_weight_and_status_element(tvb, offset, length, pinfo, info_tree);
1760 /* 6.9 Assignment Weight and Status Data Element */
1761 static int
1762 dissect_wccp2_assignment_weight_and_status_element(tvbuff_t *tvb, int offset, int length,
1763 packet_info *pinfo _U_,
1764 proto_tree *info_tree)
1767 if (length < 4)
1768 return length - 4;
1771 proto_tree_add_item(info_tree, hf_assignment_weight, tvb, offset, 2, ENC_BIG_ENDIAN);
1772 EAT_AND_CHECK(2,2);
1773 proto_tree_add_item(info_tree, hf_assignment_status, tvb, offset, 2, ENC_BIG_ENDIAN);
1774 EAT(2);
1775 return length;
1779 /* 6.10 Extended Assignment Data Element */
1780 static int
1781 dissect_wccp2_extended_assignment_data_element(tvbuff_t *tvb, int offset, int length, packet_info *pinfo,
1782 proto_tree *info_tree, wccp_address_table* addr_table)
1784 proto_item *element_item, *header;
1785 proto_tree *item_tree;
1787 unsigned type_of_assignment;
1789 int assignment_length;
1791 if (length < 4)
1792 return length-4;
1795 item_tree = proto_tree_add_subtree(info_tree, tvb, offset, length,
1796 ett_extended_assigment_data_element, &header, "Extended Assignment Data Element");
1798 type_of_assignment = tvb_get_ntohs(tvb, offset);
1799 proto_tree_add_item(item_tree, hf_extended_assignment_data_type, tvb, offset, 2, ENC_BIG_ENDIAN);
1800 EAT_AND_CHECK(2,2);
1802 assignment_length = tvb_get_ntohs(tvb,offset);
1803 element_item = proto_tree_add_item(item_tree, hf_extended_assignment_data_length, tvb, offset, 2, ENC_BIG_ENDIAN);
1804 EAT(2);
1806 if (length < assignment_length)
1807 expert_add_info_format(pinfo, element_item, &ei_wccp_assignment_length_bad,
1808 "Assignment length is %d but only %d remain in the packet. Ignoring this for now",
1809 assignment_length, length);
1811 /* Now a common bug seems to be to set the assignment_length to the length -4
1812 check for this */
1813 if ((length > assignment_length) &&
1814 (length == (assignment_length + 4)))
1816 expert_add_info_format(pinfo, element_item, &ei_wccp_assignment_length_bad,
1817 "Assignment length is %d but %d remain in the packet. Assuming that this is wrong as this is only 4 bytes too small, proceeding with the assumption it is %d",
1818 assignment_length, length, length);
1819 assignment_length = length;
1823 proto_item_set_len(header, assignment_length+4);
1825 switch (type_of_assignment)
1827 case WCCP2_HASH_ASSIGNMENT_TYPE:
1828 dissect_wccp2_hash_assignment_data_element(tvb, offset, assignment_length,
1829 pinfo, item_tree);
1830 return length - assignment_length;
1831 case WCCP2_MASK_ASSIGNMENT_TYPE:
1832 dissect_wccp2_mask_assignment_data_element(tvb, offset, assignment_length,
1833 pinfo, item_tree, addr_table);
1834 return length - assignment_length;
1835 case WCCP2r1_ALT_MASK_ASSIGNMENT_TYPE:
1836 dissect_wccp2_alternate_mask_assignment_data_element(tvb, offset, assignment_length,
1837 pinfo, item_tree, addr_table);
1838 return length - assignment_length;
1839 case WCCP2r1_ASSIGNMENT_WEIGHT_STATUS:
1840 dissect_wccp2_assignment_weight_and_status_element(tvb, offset, assignment_length,
1841 pinfo, item_tree);
1842 return length - assignment_length;
1844 return length;
1852 /* 6.11 Capability Element */
1853 static int
1854 dissect_wccp2_capability_element(tvbuff_t *tvb, int offset, int length,
1855 packet_info *pinfo, proto_tree *info_tree)
1857 uint16_t capability_type;
1858 uint16_t capability_val_len;
1859 proto_item *te, *header, *tf;
1860 proto_tree *element_tree;
1862 if (length < 4)
1863 return length - 4;
1865 capability_type = tvb_get_ntohs(tvb, offset);
1866 element_tree = proto_tree_add_subtree_format(info_tree, tvb, offset, -1, ett_capability_element, &te,
1867 "Type: %s",
1868 val_to_str(capability_type,
1869 capability_type_vals,
1870 "Unknown (0x%08X)"));
1871 header = te;
1873 proto_tree_add_item(element_tree, hf_capability_element_type, tvb, offset, 2, ENC_BIG_ENDIAN);
1875 capability_val_len = tvb_get_ntohs(tvb, offset+2);
1876 tf = proto_tree_add_uint(element_tree, hf_capability_element_length, tvb, offset+2, 2, capability_val_len);
1877 proto_item_set_len(te, capability_val_len + 4);
1879 if (length < (4+capability_val_len))
1880 return length - (4 + capability_val_len);
1882 switch (capability_type) {
1883 case WCCP2_FORWARDING_METHOD:
1884 dissect_32_bit_capability_flags(tvb, offset,
1885 capability_val_len,
1886 ett_capability_forwarding_method,
1887 forwarding_method_flags, element_tree,
1888 header, tf, pinfo);
1889 break;
1891 case WCCP2_ASSIGNMENT_METHOD:
1892 dissect_32_bit_capability_flags(tvb, offset,
1893 capability_val_len,
1894 ett_capability_assignment_method,
1895 assignment_method_flags, element_tree,
1896 header, tf, pinfo);
1897 break;
1899 case WCCP2_PACKET_RETURN_METHOD:
1900 dissect_32_bit_capability_flags(tvb, offset,
1901 capability_val_len,
1902 ett_capability_return_method,
1903 packet_return_method_flags, element_tree,
1904 header, tf, pinfo);
1905 break;
1907 case WCCP2_TRANSMIT_T:
1908 dissect_transmit_t_capability(tvb, te, offset,
1909 capability_val_len,
1910 ett_capability_transmit_t, element_tree,
1911 tf, pinfo);
1912 break;
1914 case WCCP2_TIMER_SCALE:
1915 dissect_timer_scale_capability(tvb, offset,
1916 capability_val_len,
1917 ett_capability_timer_scale, element_tree,
1918 tf, pinfo);
1919 break;
1920 default:
1921 proto_tree_add_item(element_tree, hf_capability_value, tvb, offset, capability_val_len, ENC_NA);
1922 break;
1924 return length - 4 - capability_val_len;
1928 /* 6.13 Mask/Value Set List */
1929 static int
1930 dissect_wccp2_mask_value_set_list(tvbuff_t *tvb, int offset,
1931 int length, packet_info *pinfo, proto_tree *info_tree, wccp_address_table* addr_table)
1933 unsigned num_of_elem;
1934 unsigned i;
1935 proto_item *te;
1936 proto_tree *element_tree;
1937 unsigned start;
1940 if (length < 4)
1941 return length - 4;
1943 element_tree = proto_tree_add_subtree(info_tree, tvb, offset, 4, ett_mv_set_list, &te, "Mask/Value Set List");
1944 start = offset;
1947 num_of_elem = tvb_get_ntohl(tvb, offset);
1948 proto_tree_add_item(element_tree, hf_mask_value_set_list_num_elements,
1949 tvb, offset, 4, ENC_BIG_ENDIAN);
1950 /* proto_tree_add_uint(element_tree, , tvb, offset, 4, num_of_elem); */
1951 EAT(4);
1953 for (i = 0; i < num_of_elem; i++)
1955 int new_length;
1957 new_length=dissect_wccp2_mask_value_set_element(tvb, offset, length, i, pinfo, element_tree, addr_table);
1959 CHECK_LENGTH_ADVANCE_OFFSET(new_length);
1962 proto_item_set_len(te, offset-start);
1963 return length;
1970 /* 6.15 Mask Element */
1971 static int
1972 dissect_wccp2_mask_element(tvbuff_t *tvb, int offset, int length, packet_info *pinfo _U_, proto_tree *info_tree)
1974 if (length < 2)
1975 return length-12;
1977 proto_tree_add_item(info_tree, hf_mask_element_src_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1978 EAT_AND_CHECK(4,4);
1979 proto_tree_add_item(info_tree, hf_mask_element_dest_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1981 EAT_AND_CHECK(4,2);
1982 proto_tree_add_item(info_tree, hf_mask_element_src_port, tvb, offset, 2, ENC_BIG_ENDIAN);
1983 EAT_AND_CHECK(2,2);
1984 proto_tree_add_item(info_tree, hf_mask_element_dest_port, tvb, offset, 2, ENC_BIG_ENDIAN);
1985 EAT(2);
1987 return length;
1995 /* 6.17 Alternate Mask/Value Set List */
1996 static int dissect_wccp2_alternate_mask_value_set_list(tvbuff_t *tvb, int offset,
1997 int length, packet_info *pinfo, proto_tree *info_tree, wccp_address_table* addr_table)
1999 proto_tree *list_tree;
2000 unsigned num_of_val_elements;
2001 unsigned i;
2003 if (length < 4)
2004 return length - 4;
2006 list_tree = proto_tree_add_subtree(info_tree, tvb, offset, length,
2007 ett_alternate_mask_value_set, NULL, "Alternate Mask/Value Set List");
2009 num_of_val_elements = tvb_get_ntohl(tvb, offset);
2010 proto_tree_add_uint(list_tree, hf_alt_assignment_mask_value_set_list_num_elements, tvb, offset, 4, num_of_val_elements);
2011 EAT(4);
2013 for(i=0;i<num_of_val_elements;i++) {
2014 int new_length;
2016 new_length=dissect_wccp2_alternate_mask_value_set_element(tvb, offset, length, i, pinfo, list_tree, addr_table);
2018 CHECK_LENGTH_ADVANCE_OFFSET(new_length);
2020 return length;
2024 /* 6.18 Alternate Mask/Value Set Element */
2025 static int
2026 dissect_wccp2_alternate_mask_value_set_element(tvbuff_t *tvb, int offset, int length, unsigned el_index, packet_info *pinfo,
2027 proto_tree *info_tree, wccp_address_table* addr_table)
2029 proto_item *tl, *header;
2030 proto_tree *element_tree, *value_tree;
2031 unsigned number_of_elements;
2032 int new_length, total_length;
2033 unsigned i;
2035 element_tree = proto_tree_add_subtree_format(info_tree, tvb, offset, 0,
2036 ett_alternate_mask_value_set_element, &header,
2037 "Alternate Mask/Value Set Element(%d)", el_index);
2039 total_length = 0;
2041 new_length=dissect_wccp2_mask_element(tvb,offset,length,pinfo,element_tree);
2042 total_length += length - new_length;
2043 CHECK_LENGTH_ADVANCE_OFFSET(new_length);
2045 if (length < 4)
2046 return length - 4;
2048 number_of_elements = tvb_get_ntohl(tvb, offset);
2049 tl = proto_tree_add_uint(element_tree, hf_alt_assignment_mask_value_set_element_num_wc_value_elements, tvb, offset, 4, number_of_elements);
2050 value_tree = proto_item_add_subtree(tl, ett_alternate_mv_set_element_list);
2051 total_length += 4;
2052 EAT(4);
2054 /* XXX Add a bounds check for number_of_elements? */
2055 for (i=0; i < number_of_elements; i++) {
2056 new_length=dissect_wccp2_web_cache_value_element(tvb, offset, length, pinfo, value_tree, addr_table);
2057 total_length += length - new_length;
2058 CHECK_LENGTH_ADVANCE_OFFSET(new_length);
2060 proto_item_set_len(header, total_length);
2062 return length;
2065 /* 6.19 Web-Cache Value Element */
2066 static int
2067 dissect_wccp2_web_cache_value_element(tvbuff_t *tvb, int offset, int length, packet_info *pinfo _U_, proto_tree *info_tree, wccp_address_table* addr_table)
2069 unsigned number_of_elements, seq_num;
2070 proto_item *tl;
2071 proto_tree *element_tree;
2072 unsigned i;
2074 if (length < 4)
2075 return length - 8;
2077 tl = wccp_add_ipaddress_item(info_tree, hf_web_cache_value_element_wc_address_index, hf_web_cache_value_element_wc_address_ipv4, hf_web_cache_value_element_wc_address_ipv6, tvb, offset, 4, addr_table);
2079 element_tree = proto_item_add_subtree(tl, ett_web_cache_value_element_list);
2080 EAT_AND_CHECK(4,4);
2082 number_of_elements = tvb_get_ntohl(tvb, offset);
2083 proto_tree_add_uint(element_tree, hf_web_cache_value_element_num_values, tvb, offset, 4, number_of_elements);
2084 EAT(4);
2086 for (i=0; i < number_of_elements; i++) {
2087 if (length < 4)
2088 return length - 4*(number_of_elements-i);
2090 seq_num = tvb_get_ntohl(tvb, offset);
2091 proto_tree_add_uint_format(element_tree, hf_web_cache_value_seq_num, tvb, offset, 4,
2092 seq_num, "Value Sequence Number %d: %x", i+1, seq_num);
2093 EAT(4);
2096 return length;
2100 /* End of standard functions */
2103 static void
2104 dissect_32_bit_capability_flags(tvbuff_t *tvb, int curr_offset,
2105 uint16_t capability_val_len, int ett, const capability_flag *flags,
2106 proto_tree *element_tree, proto_item *header,
2107 proto_item *length_item, packet_info *pinfo)
2109 uint32_t capability_val;
2110 proto_item *tm;
2111 proto_tree *method_tree;
2112 int i;
2113 bool first = true;
2115 if (capability_val_len != 4) {
2116 expert_add_info_format(pinfo, length_item, &ei_wccp_capability_element_length,
2117 "Value Length: %u (illegal, must be == 4)", capability_val_len);
2118 return;
2121 capability_val = tvb_get_ntohl(tvb, curr_offset + 4);
2122 tm = proto_tree_add_uint(element_tree, hf_capability_info_value, tvb, curr_offset + 4, 4, capability_val);
2124 for (i = 0; flags[i].short_name != NULL; i++) {
2125 if (capability_val & flags[i].value) {
2126 if (first) {
2127 proto_item_append_text( tm, " (%s", flags[i].short_name);
2128 proto_item_append_text( header, " (%s", flags[i].short_name);
2129 first = false;
2130 } else {
2131 proto_item_append_text( tm, ", %s", flags[i].short_name);
2132 proto_item_append_text( header, " (%s", flags[i].short_name);
2137 if (first == false) {
2138 proto_item_append_text( tm, ")");
2139 proto_item_append_text( header, ")");
2142 method_tree = proto_item_add_subtree(tm, ett);
2143 for (i = 0; flags[i].phf != NULL; i++)
2144 proto_tree_add_item(method_tree, *(flags[i].phf), tvb, curr_offset+4, 4, ENC_BIG_ENDIAN);
2149 /* 6.11.4 Capability Type WCCP2_TRANSMIT_T */
2150 static void
2151 dissect_transmit_t_capability(tvbuff_t *tvb, proto_item *te, int curr_offset,
2152 uint16_t capability_val_len, int ett, proto_tree *element_tree,
2153 proto_item *length_item, packet_info *pinfo)
2155 uint16_t upper_limit, lower_limit;
2156 proto_tree *method_tree;
2158 if (capability_val_len != 4) {
2159 expert_add_info_format(pinfo, length_item, &ei_wccp_capability_element_length,
2160 "Value Length: %u (illegal, must be == 4)", capability_val_len);
2161 return;
2164 upper_limit = tvb_get_ntohs(tvb, curr_offset);
2165 lower_limit = tvb_get_ntohs(tvb, curr_offset + 2);
2167 if ( upper_limit == 0) {
2168 method_tree = proto_tree_add_subtree(element_tree, tvb, curr_offset, 2,
2169 ett, NULL, "Only accepting one value");
2170 proto_tree_add_uint(method_tree, hf_reserved_zero, tvb, curr_offset, 2, upper_limit);
2172 proto_tree_add_item(method_tree, hf_capability_transmit_t , tvb, curr_offset+2, 2, ENC_BIG_ENDIAN);
2173 proto_item_append_text(te, " %d ms", lower_limit);
2174 } else {
2175 method_tree = proto_tree_add_subtree(element_tree, tvb, curr_offset, 2,
2176 ett, NULL, "Accepting a range");
2177 proto_tree_add_item(method_tree, hf_capability_transmit_t_upper_limit,
2178 tvb, curr_offset, 2, ENC_BIG_ENDIAN);
2180 proto_tree_add_item(method_tree, hf_capability_transmit_t_lower_limit,
2181 tvb, curr_offset+2, 2, ENC_BIG_ENDIAN);
2182 proto_item_append_text(te, " < %d ms > %d ms", lower_limit, upper_limit);
2187 static void
2188 dissect_timer_scale_capability(tvbuff_t *tvb, int curr_offset,
2189 uint16_t capability_val_len, int ett, proto_tree *element_tree,
2190 proto_item *length_item, packet_info *pinfo)
2192 uint8_t a,c;
2193 proto_tree *method_tree;
2195 if (capability_val_len != 4) {
2196 expert_add_info_format(pinfo, length_item, &ei_wccp_capability_element_length,
2197 "Value Length: %u (illegal, must be == 4)", capability_val_len);
2198 return;
2201 a = tvb_get_uint8(tvb, curr_offset);
2202 c = tvb_get_uint8(tvb, curr_offset+2);
2204 if ( a == 0) {
2205 if ( c == 0) {
2206 method_tree = proto_tree_add_subtree(element_tree, tvb, curr_offset, 2,
2207 ett, NULL, "Only accepting one value");
2209 proto_tree_add_uint(method_tree, hf_reserved_zero, tvb, curr_offset, 1, a);
2211 proto_tree_add_item(method_tree, hf_capability_timer_scale_timeout_scale,
2212 tvb, curr_offset+1, 1, ENC_BIG_ENDIAN);
2213 proto_tree_add_uint(method_tree, hf_reserved_zero, tvb, curr_offset+2, 1, c);
2214 proto_tree_add_item(method_tree, hf_capability_timer_scale_ra_timer_scale,
2215 tvb, curr_offset+3, 1, ENC_BIG_ENDIAN);
2216 } else {
2217 proto_tree_add_expert(element_tree, pinfo, &ei_wccp_a_zero_not_c, tvb, curr_offset, 1);
2219 } else {
2220 if ( c == 0) {
2221 proto_tree_add_expert(element_tree, pinfo, &ei_wccp_a_zero_not_c, tvb, curr_offset, 1);
2222 } else {
2223 method_tree = proto_tree_add_subtree(element_tree, tvb, curr_offset, 2,
2224 ett, NULL, "Accepting a range");
2225 proto_tree_add_item(method_tree, hf_capability_timer_scale_timeout_scale_upper_limit,
2226 tvb, curr_offset, 1, ENC_BIG_ENDIAN);
2228 proto_tree_add_item(method_tree, hf_capability_timer_scale_timeout_scale_lower_limit,
2229 tvb, curr_offset+1, 1, ENC_BIG_ENDIAN);
2230 proto_tree_add_item(method_tree, hf_capability_timer_scale_ra_scale_upper_limit,
2231 tvb, curr_offset+2, 1, ENC_BIG_ENDIAN);
2232 proto_tree_add_item(method_tree, hf_capability_timer_scale_ra_scale_lower_limit,
2233 tvb, curr_offset+3, 1, ENC_BIG_ENDIAN);
2239 /* 6.16 Value Element */
2240 static int
2241 dissect_wccp2_value_element(tvbuff_t *tvb, int offset, int length, int idx, packet_info *pinfo, proto_tree *info_tree, wccp_address_table* addr_table)
2243 proto_tree *element_tree;
2245 if (length < 4)
2246 return length - 16;
2248 element_tree = proto_tree_add_subtree_format(info_tree, tvb, offset, 16, ett_value_element, NULL, "Value Element(%u) %s",
2249 idx,decode_wccp_encoded_address(tvb, offset+4+4+2+2, pinfo, info_tree, addr_table));
2252 wccp_add_ipaddress_item(info_tree, hf_value_element_src_ip_index, hf_value_element_src_ipv4, hf_value_element_src_ipv6, tvb, offset, 4, addr_table);
2253 EAT_AND_CHECK(4,4);
2254 wccp_add_ipaddress_item(info_tree, hf_value_element_dest_ip_index, hf_value_element_dest_ipv4, hf_value_element_dest_ipv6, tvb, offset, 4, addr_table);
2256 EAT_AND_CHECK(4,2);
2257 proto_tree_add_item(element_tree, hf_value_element_src_port, tvb, offset, 2, ENC_BIG_ENDIAN);
2258 EAT_AND_CHECK(2,2);
2259 proto_tree_add_item(element_tree, hf_value_element_dest_port, tvb, offset, 2, ENC_BIG_ENDIAN);
2260 EAT_AND_CHECK(2,4);
2262 wccp_add_ipaddress_item(info_tree, hf_value_element_web_cache_ip_index, hf_value_element_web_cache_ipv4, hf_value_element_web_cache_ipv6, tvb, offset, 4, addr_table);
2263 EAT(4);
2265 return length;
2269 /* 6.14 Mask/Value Set Element */
2270 static int
2271 dissect_wccp2_mask_value_set_element(tvbuff_t *tvb, int offset, int length, int idx, packet_info *pinfo, proto_tree *info_tree, wccp_address_table* addr_table)
2273 proto_item *tl, *te;
2274 proto_tree *element_tree, *value_tree;
2275 unsigned num_of_val_elements;
2276 unsigned i;
2277 int new_length;
2279 element_tree = proto_tree_add_subtree_format(info_tree, tvb, offset, 0,
2280 ett_mv_set_element, &tl, "Mask/Value Set Element(%d)", idx);
2282 new_length = dissect_wccp2_mask_element(tvb,offset,length,pinfo,element_tree);
2283 CHECK_LENGTH_ADVANCE_OFFSET(new_length);
2285 if (length < 4)
2286 return length-4;
2288 num_of_val_elements = tvb_get_ntohl(tvb, offset);
2289 te = proto_tree_add_uint(element_tree, hf_mask_value_set_element_value_element_num, tvb, offset, 4, num_of_val_elements);
2291 value_tree = proto_item_add_subtree(te, ett_mv_set_value_list);
2292 EAT(4);
2294 for (i = 0; i < num_of_val_elements; i++)
2296 new_length=dissect_wccp2_value_element(tvb, offset, length, i, pinfo, value_tree, addr_table);
2298 CHECK_LENGTH_ADVANCE_OFFSET(new_length);
2301 proto_item_set_len(tl, 16+num_of_val_elements*16);
2303 return length;
2306 #define ALT_ASSIGNMENT_INFO_MIN_LEN (4+4)
2308 /* 5.4.2 Alternate Assignment Component */
2309 static int
2310 dissect_wccp2_alternate_assignment_info(tvbuff_t *tvb, int offset, int length,
2311 packet_info *pinfo, proto_tree *info_tree, wccp_address_table* addr_table)
2313 uint16_t assignment_type;
2314 uint16_t assignment_length;
2315 proto_item *tf=NULL;
2317 uint32_t n_routers;
2318 unsigned i;
2319 proto_tree *element_tree;
2320 int new_length;
2323 if (length < ALT_ASSIGNMENT_INFO_MIN_LEN)
2324 return length - ALT_ASSIGNMENT_INFO_MIN_LEN;
2327 assignment_type = tvb_get_ntohs(tvb, offset);
2328 proto_tree_add_item(info_tree, hf_alt_assignment_info_assignment_type, tvb, offset, 2, ENC_BIG_ENDIAN);
2329 EAT_AND_CHECK(2,2);
2331 assignment_length = tvb_get_ntohs(tvb, offset);
2332 tf=proto_tree_add_item(info_tree, hf_alt_assignment_info_assignment_length, tvb, offset, 2, ENC_BIG_ENDIAN);
2333 EAT(2);
2335 if (length < assignment_length)
2336 expert_add_info_format(pinfo, tf, &ei_wccp_assignment_length_bad,
2337 "Assignment length is %d but only %d remain in the packet. Ignoring this for now",
2338 assignment_length, length);
2340 if (length > assignment_length) {
2341 expert_add_info_format(pinfo, tf, &ei_wccp_assignment_length_bad,
2342 "Assignment length is %d but %d remain in the packet. Assuming that the assignment length is wrong and setting it to %d.",
2343 assignment_length, length, length);
2346 new_length=dissect_wccp2_assignment_key_element(tvb, offset, length, pinfo, info_tree, addr_table);
2347 CHECK_LENGTH_ADVANCE_OFFSET(new_length);
2349 n_routers = tvb_get_ntohl(tvb, offset);
2350 proto_tree_add_uint(info_tree, hf_alt_assignment_info_num_routers, tvb, offset, 4, n_routers);
2351 EAT(4);
2353 for (i = 0; i < n_routers; i++) {
2354 if (length < 12)
2355 return length - 12*(n_routers-i);
2357 element_tree = proto_tree_add_subtree_format(info_tree, tvb, offset, 12,
2358 ett_router_alt_assignment_element, NULL,
2359 "Router %d Assignment Element: IP address %s", i,
2360 decode_wccp_encoded_address(tvb, offset, pinfo, info_tree, addr_table));
2362 dissect_wccp2_router_assignment_element(tvb, offset, length , pinfo, element_tree, addr_table);
2363 EAT(12);
2366 switch (assignment_type) {
2367 case WCCP2_HASH_ASSIGNMENT_TYPE:
2368 return dissect_wccp2_hash_assignment_info(tvb, offset, length,
2369 pinfo, info_tree, addr_table);
2370 case WCCP2_MASK_ASSIGNMENT_TYPE:
2371 return dissect_wccp2_mask_value_set_list(tvb, offset, length,
2372 pinfo, info_tree, addr_table);
2373 case WCCP2r1_ALT_MASK_ASSIGNMENT_TYPE:
2374 return dissect_wccp2_alternate_mask_value_set_list(tvb, offset, length,
2375 pinfo, info_tree, addr_table);
2376 default:
2377 return length;
2381 static void
2382 dissect_wccp2_info(tvbuff_t *tvb, int offset,
2383 packet_info *pinfo, proto_tree *wccp_tree,
2384 uint32_t message_type)
2386 uint16_t type;
2387 uint16_t item_length;
2388 proto_item *tf;
2389 proto_tree *info_tree;
2390 int ett;
2391 int (*dissector)(tvbuff_t *, int, int, packet_info *, proto_tree *, wccp_address_table*);
2393 /* check if all required fields are there */
2394 bool wccp2_security_info;
2395 bool wccp2_service_info;
2396 bool wccp2_router_id_info;
2397 bool wccp2_wc_id_info;
2398 bool wccp2_rtr_view_info;
2399 bool wccp2_wc_view_info;
2400 bool wccp2_redirect_assignment;
2401 bool wccp2_query_info;
2402 bool wccp2_capabilities_info;
2403 bool wccp2_alt_assignment;
2404 bool wccp2_assign_map;
2405 bool wccp2_command_extension;
2406 bool wccp2r1_alt_assignment_map;
2407 wccp_address_table wccp_wccp_address_table = {false, -1, -1, 0, NULL, NULL};
2409 wccp2_security_info=false;
2410 wccp2_service_info=false;
2411 wccp2_router_id_info=false;
2412 wccp2_wc_id_info=false;
2413 wccp2_rtr_view_info=false;
2414 wccp2_wc_view_info=false;
2415 wccp2_redirect_assignment=false;
2416 wccp2_query_info=false;
2417 wccp2_capabilities_info=false;
2418 wccp2_alt_assignment=false;
2419 wccp2_assign_map=false;
2420 wccp2_command_extension=false;
2421 wccp2r1_alt_assignment_map=false;
2423 /* ugly hack: we first need to check for the address table
2424 component, otherwise we cannot print the IP's.
2426 find_wccp_address_table(tvb,offset,pinfo,wccp_tree, &wccp_wccp_address_table);
2428 while (tvb_reported_length_remaining(tvb, offset) > 0) {
2429 type = tvb_get_ntohs(tvb, offset);
2430 switch (type) {
2432 case WCCP2_SECURITY_INFO:
2433 wccp2_security_info=true;
2434 ett = ett_security_info;
2435 dissector = dissect_wccp2_security_info;
2436 break;
2438 case WCCP2_SERVICE_INFO:
2439 wccp2_service_info=true;
2440 ett = ett_service_info;
2441 dissector = dissect_wccp2_service_info;
2442 break;
2444 case WCCP2_ROUTER_ID_INFO:
2445 wccp2_router_id_info=true;
2446 ett = ett_router_identity_info;
2447 dissector = dissect_wccp2_router_identity_info;
2448 break;
2450 case WCCP2_WC_ID_INFO:
2451 wccp2_wc_id_info=true;
2452 ett = ett_wc_identity_info;
2453 dissector = dissect_wccp2_wc_identity_info;
2454 break;
2456 case WCCP2_RTR_VIEW_INFO:
2457 wccp2_rtr_view_info=true;
2458 ett = ett_router_view_info;
2459 dissector = dissect_wccp2_router_view_info;
2460 break;
2462 case WCCP2_WC_VIEW_INFO:
2463 wccp2_wc_view_info=true;
2464 ett = ett_wc_view_info;
2465 dissector = dissect_wccp2_web_cache_view_info;
2466 break;
2468 case WCCP2_REDIRECT_ASSIGNMENT:
2469 wccp2_redirect_assignment=true;
2470 ett = ett_router_assignment_info;
2471 dissector = dissect_wccp2_assignment_info;
2472 break;
2474 case WCCP2_QUERY_INFO:
2475 wccp2_query_info=true;
2476 ett = ett_query_info;
2477 dissector = dissect_wccp2_router_query_info;
2478 break;
2480 case WCCP2_CAPABILITIES_INFO:
2481 wccp2_capabilities_info=true;
2482 ett = ett_capabilities_info;
2483 dissector = dissect_wccp2_capability_info;
2484 break;
2486 case WCCP2_ALT_ASSIGNMENT:
2487 wccp2_alt_assignment=true;
2488 ett = ett_alt_assignment_info;
2489 dissector = dissect_wccp2_alternate_assignment_info;
2490 break;
2492 case WCCP2r1_ALT_ASSIGNMENT_MAP:
2493 wccp2r1_alt_assignment_map=true;
2494 ett = ett_alt_assignment_map;
2495 dissector = dissect_wccp2r1_alt_assignment_map_info;
2496 break;
2498 case WCCP2r1_ADDRESS_TABLE:
2499 ett = ett_address_table;
2500 dissector = dissect_wccp2r1_address_table_info;
2501 break;
2503 case WCCP2_ASSIGN_MAP:
2504 wccp2_assign_map=true;
2505 ett = ett_assignment_map;
2506 dissector = dissect_wccp2_assignment_map;
2507 break;
2508 case WCCP2_COMMAND_EXTENSION:
2509 wccp2_command_extension=true;
2510 ett = ett_command_extension;
2511 dissector = dissect_wccp2_command_extension;
2512 break;
2514 default:
2515 ett = ett_unknown_info;
2516 dissector = NULL;
2517 break;
2520 info_tree = proto_tree_add_subtree(wccp_tree, tvb, offset, -1, ett, &tf,
2521 val_to_str(type, info_type_vals, "Unknown info type (%u)"));
2523 proto_tree_add_item(info_tree, hf_item_type, tvb, offset, 2, ENC_BIG_ENDIAN);
2525 item_length = tvb_get_ntohs(tvb, offset+2);
2526 proto_tree_add_item(info_tree, hf_item_length, tvb, offset+2, 2, ENC_BIG_ENDIAN);
2528 offset += 4;
2530 if (dissector != NULL) {
2531 int remaining_item_length = (*dissector)(tvb, offset, item_length, pinfo, info_tree, &wccp_wccp_address_table);
2533 /* warn if we left bytes */
2534 if (remaining_item_length > 0)
2535 expert_add_info_format(pinfo, tf, &ei_wccp_length_bad,
2536 "The item is %d bytes too long",
2537 remaining_item_length);
2539 /* error if we needed more bytes */
2540 if (remaining_item_length < 0)
2541 expert_add_info_format(pinfo, tf, &ei_wccp_length_bad,
2542 "The item is %d bytes too short",
2543 -remaining_item_length);
2545 /* we assume that the item length is correct and jump forward */
2546 } else {
2547 proto_tree_add_item(info_tree, hf_item_data, tvb, offset, item_length, ENC_NA);
2550 offset += item_length;
2551 proto_item_set_end(tf, tvb, offset);
2555 /* we're done. Check if we got all the required components */
2557 switch (message_type) {
2558 case WCCP2_HERE_I_AM:
2559 if (!wccp2_security_info)
2560 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_security_info);
2561 if (!wccp2_service_info)
2562 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_service_info);
2563 if (wccp2_router_id_info)
2564 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_router_id_info);
2565 if (!wccp2_wc_id_info)
2566 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_wc_id_info);
2567 if (wccp2_rtr_view_info)
2568 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_rtr_view_info);
2569 if (!wccp2_wc_view_info)
2570 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_wc_view_info);
2571 if (wccp2_redirect_assignment)
2572 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_redirect_assignment);
2573 if (wccp2_query_info)
2574 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_query_info);
2575 if (wccp2_alt_assignment)
2576 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_alt_assignment);
2577 if (wccp2_assign_map)
2578 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_assign_map);
2579 if (wccp2r1_alt_assignment_map)
2580 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_alt_assignment_map);
2581 break;
2582 case WCCP2_I_SEE_YOU:
2583 if (!wccp2_security_info)
2584 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_security_info);
2585 if (!wccp2_service_info)
2586 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_service_info);
2587 if (!wccp2_router_id_info)
2588 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_router_id_info);
2589 if (wccp2_wc_id_info)
2590 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_wc_id_info);
2591 if (!wccp2_rtr_view_info)
2592 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_rtr_view_info);
2593 if (wccp2_wc_view_info)
2594 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_wc_view_info);
2595 if (wccp2_redirect_assignment)
2596 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_redirect_assignment);
2597 if (wccp2_query_info)
2598 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_query_info);
2599 if (wccp2r1_alt_assignment_map)
2600 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_alt_assignment_map);
2601 break;
2603 case WCCP2_REMOVAL_QUERY:
2604 if (!wccp2_security_info)
2605 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_security_info);
2606 if (!wccp2_service_info)
2607 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_service_info);
2608 if (wccp2_router_id_info)
2609 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_router_id_info);
2610 if (wccp2_wc_id_info)
2611 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_wc_id_info);
2612 if (wccp2_rtr_view_info)
2613 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_rtr_view_info);
2614 if (wccp2_wc_view_info)
2615 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_wc_view_info);
2616 if (wccp2_redirect_assignment)
2617 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_redirect_assignment);
2618 if (!wccp2_query_info)
2619 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_query_info);
2620 if (wccp2_capabilities_info)
2621 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_capabilities_info);
2622 if (wccp2_alt_assignment)
2623 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_alt_assignment);
2624 if (wccp2_assign_map)
2625 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_assign_map);
2626 if (wccp2_command_extension)
2627 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_command_extension);
2628 if (wccp2r1_alt_assignment_map)
2629 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_alt_assignment_map);
2630 break;
2632 case WCCP2_REDIRECT_ASSIGN:
2633 if (!wccp2_security_info)
2634 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_security_info);
2635 if (!wccp2_service_info)
2636 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_service_info);
2637 if (wccp2_router_id_info)
2638 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_router_id_info);
2639 if (wccp2_wc_id_info)
2640 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_wc_id_info);
2641 if (wccp2_rtr_view_info)
2642 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_rtr_view_info);
2643 if (wccp2_wc_view_info)
2644 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_wc_view_info);
2645 if (wccp2_query_info)
2646 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_query_info);
2647 if (wccp2_capabilities_info)
2648 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_capabilities_info);
2649 if (! (wccp2_assign_map || wccp2r1_alt_assignment_map || wccp2_alt_assignment || wccp2_redirect_assignment))
2650 expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_assignment);
2651 if (wccp2_command_extension)
2652 expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_command_extension);
2653 break;
2657 static int
2658 dissect_wccp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
2660 int offset = 0;
2661 proto_tree *wccp_tree = NULL;
2662 proto_item *wccp_tree_item;
2663 uint32_t wccp_message_type;
2664 uint16_t length;
2665 int wccp2_length;
2666 proto_item *length_item;
2667 uint32_t cache_count;
2668 uint32_t ipaddr;
2669 unsigned i;
2670 uint8_t bucket;
2672 wccp_message_type = tvb_get_ntohl(tvb, offset);
2674 /* Check if this is really a WCCP message */
2675 if (try_val_to_str(wccp_message_type, wccp_type_vals) == NULL)
2676 return 0;
2678 col_set_str(pinfo->cinfo, COL_PROTOCOL, "WCCP");
2680 col_add_str(pinfo->cinfo, COL_INFO, val_to_str(wccp_message_type,
2681 wccp_type_vals, "Unknown WCCP message (%u)"));
2683 wccp_tree_item = proto_tree_add_item(tree, proto_wccp, tvb, offset, -1, ENC_NA);
2684 wccp_tree = proto_item_add_subtree(wccp_tree_item, ett_wccp);
2686 proto_tree_add_uint(wccp_tree, hf_wccp_message_type, tvb, offset, 4, wccp_message_type);
2687 offset += 4;
2689 switch (wccp_message_type) {
2691 case WCCP_HERE_I_AM:
2692 proto_tree_add_item(wccp_tree, hf_wccp_version, tvb,
2693 offset, 4, ENC_BIG_ENDIAN);
2694 offset += 4;
2695 offset = dissect_hash_data(tvb, offset, wccp_tree);
2696 proto_tree_add_item(wccp_tree, hf_recvd_id, tvb, offset,
2697 4, ENC_BIG_ENDIAN);
2698 /*offset += 4;*/
2699 break;
2701 case WCCP_I_SEE_YOU:
2702 proto_tree_add_item(wccp_tree, hf_wccp_version, tvb,
2703 offset, 4, ENC_BIG_ENDIAN);
2704 offset += 4;
2705 proto_tree_add_item(wccp_tree, hf_change_num, tvb, offset,
2706 4, ENC_BIG_ENDIAN);
2707 offset += 4;
2708 proto_tree_add_item(wccp_tree, hf_recvd_id, tvb, offset,
2709 4, ENC_BIG_ENDIAN);
2710 offset += 4;
2711 cache_count = tvb_get_ntohl(tvb, offset);
2712 proto_tree_add_uint(wccp_tree, hf_wc_num, tvb, offset, 4, cache_count);
2713 offset += 4;
2714 for (i = 0; i < cache_count; i++) {
2715 offset = dissect_web_cache_list_entry(tvb, offset, i,
2716 wccp_tree);
2718 break;
2720 case WCCP_ASSIGN_BUCKET:
2722 * This hasn't been tested, since I don't have any
2723 * traces with this in it.
2725 * The V1 spec claims that this does, indeed,
2726 * have a Received ID field after the type,
2727 * rather than a Version field.
2729 proto_tree_add_item(wccp_tree, hf_recvd_id, tvb, offset,
2730 4, ENC_BIG_ENDIAN);
2731 offset += 4;
2732 cache_count = tvb_get_ntohl(tvb, offset);
2733 proto_tree_add_uint(wccp_tree, hf_wc_num, tvb, offset, 4, cache_count);
2734 offset += 4;
2735 for (i = 0; i < cache_count; i++) {
2736 ipaddr = tvb_get_ipv4(tvb, offset);
2737 proto_tree_add_ipv4_format(wccp_tree,
2738 hf_cache_ip, tvb, offset, 4,
2739 ipaddr,
2740 "Web Cache %d IP Address: %s", i,
2741 tvb_ip_to_str(pinfo->pool, tvb, offset));
2742 offset += 4;
2745 for (i = 0; i < 256; i++) {
2746 bucket = tvb_get_uint8(tvb, offset);
2747 if (bucket == 0xff) {
2748 proto_tree_add_uint_format(wccp_tree, hf_bucket, tvb, offset, 1,
2749 bucket, "Bucket %d: Unassigned", i);
2750 } else {
2751 proto_tree_add_uint_format(wccp_tree, hf_bucket, tvb, offset, 1,
2752 bucket, "Bucket %d: %d", i, bucket);
2754 offset++;
2756 break;
2758 case WCCP2_HERE_I_AM:
2759 case WCCP2_I_SEE_YOU:
2760 case WCCP2_REMOVAL_QUERY:
2761 case WCCP2_REDIRECT_ASSIGN:
2762 default: /* assume unknown packets are v2 */
2763 /* 5.5 WCCP Message Header */
2765 proto_tree_add_item(wccp_tree, hf_message_header_version, tvb, offset, 2,
2766 ENC_BIG_ENDIAN);
2767 offset += 2;
2769 length = tvb_get_ntohs(tvb, offset);
2770 length_item = proto_tree_add_uint(wccp_tree, hf_message_header_length, tvb, offset, 2, length);
2771 offset += 2;
2773 /* Is the length plus the length of the data preceding it longer than
2774 the length of our packet? */
2775 wccp2_length = tvb_reported_length_remaining(tvb, offset);
2776 if (length > (unsigned)wccp2_length) {
2777 expert_add_info_format(pinfo, length_item, &ei_wccp_length_bad,
2778 "The length as specified by the length field is bigger than the length of the packet");
2779 length = wccp2_length - offset;
2780 } else {
2781 /* Truncate the packet to the specified length. */
2782 tvb_set_reported_length(tvb, offset + length);
2784 proto_item_set_len(wccp_tree_item, offset + length);
2785 dissect_wccp2_info(tvb, offset, pinfo, wccp_tree, wccp_message_type);
2786 break;
2789 return tvb_captured_length(tvb);
2794 /* End of utility functions */
2796 void
2797 proto_register_wccp(void)
2799 static hf_register_info hf[] = {
2800 { &hf_wccp_message_type,
2801 { "WCCP Message Type", "wccp.message", FT_UINT32, BASE_DEC, VALS(wccp_type_vals), 0x0,
2802 "The WCCP message that was sent", HFILL }
2804 { &hf_wccp_version,
2805 { "WCCP Version", "wccp.version", FT_UINT32, BASE_HEX, VALS(wccp_version_val), 0x0,
2806 "The WCCP version", HFILL }
2808 { &hf_bucket,
2809 { "Bucket", "wccp.bucket", FT_UINT8, BASE_DEC, 0x0, 0x0,
2810 NULL, HFILL }
2812 { &hf_bucket_bit,
2813 { "Bucket", "wccp.bucket_bit", FT_UINT8, BASE_DEC, 0x0, 0x0,
2814 NULL, HFILL }
2816 { &hf_message_header_version,
2817 { "WCCP Version (>=2)", "wccp.message_header_version", FT_UINT16, BASE_HEX, NULL, 0x0,
2818 "The WCCP version for version 2 and above", HFILL }
2820 { &hf_hash_revision,
2821 { "Hash Revision", "wccp.hash_revision", FT_UINT32, BASE_DEC, 0x0, 0x0,
2822 "The cache hash revision", HFILL }
2824 { &hf_change_num,
2825 { "Change Number", "wccp.change_num", FT_UINT32, BASE_DEC, 0x0, 0x0,
2826 "The Web-Cache list entry change number", HFILL }
2828 { &hf_hash_flag,
2829 { "Flags", "wccp.hash_flag", FT_UINT32, BASE_HEX, 0x0, 0x0,
2830 NULL, HFILL }
2832 { &hf_hash_flag_u,
2833 { "Hash information", "wccp.hash_flag.u", FT_BOOLEAN, 32, TFS(&tfs_historical_current), 0x00010000,
2834 NULL, HFILL }
2836 { &hf_recvd_id,
2837 { "Received ID", "wccp.recvd_id", FT_UINT32, BASE_DEC, 0x0, 0x0,
2838 "The number of I_SEE_YOU's that have been sent", HFILL }
2840 { &hf_cache_ip,
2841 { "Web Cache IP address", "wccp.cache_ip", FT_IPv4, BASE_NONE, NULL, 0x0,
2842 "The IP address of a Web cache", HFILL }
2844 { &hf_wc_num,
2845 { "Number of Web Caches", "wccp.wc_num", FT_UINT32, BASE_DEC, 0x0, 0x0,
2846 NULL, HFILL }
2848 { &hf_message_header_length,
2849 { "Length", "wccp.message_header_length", FT_UINT16, BASE_DEC, 0x0, 0x0,
2850 NULL, HFILL }
2852 { &hf_item_length,
2853 { "Length", "wccp.item_length", FT_UINT16, BASE_DEC, 0x0, 0x0,
2854 "The Length of the WCCPv2 item", HFILL }
2856 { &hf_item_type,
2857 { "Type", "wccp.item_type", FT_UINT16, BASE_DEC, VALS(info_type_vals), 0x0,
2858 "The type of the WCCPv2 item", HFILL }
2860 { &hf_item_data,
2861 { "Data", "wccp.item_data", FT_BYTES, BASE_NONE, 0x0, 0x0,
2862 "The data for an unknown item type", HFILL }
2864 { &hf_security_info_option,
2865 { "Security Option", "wccp.security_info_option", FT_UINT32, BASE_DEC, VALS(security_option_vals), 0x0,
2866 NULL, HFILL }
2868 { &hf_security_info_md5_checksum,
2869 { "MD5 checksum (not checked)", "wccp.security_md5_checksum", FT_BYTES, BASE_NONE, 0x0, 0x0,
2870 NULL, HFILL }
2872 { &hf_command_element_type,
2873 {"Command Extension Type", "wccp.command_element_type", FT_UINT16, BASE_DEC, VALS(wccp_command_type_vals), 0x0,
2874 NULL, HFILL }
2876 { &hf_command_element_length,
2877 {"Command Extension Length", "wccp.command_element_length", FT_UINT16, BASE_DEC, NULL, 0x0,
2878 NULL, HFILL }
2880 { &hf_command_length,
2881 {"Command Length", "wccp.command_length", FT_UINT16, BASE_DEC, NULL, 0x0,
2882 NULL, HFILL }
2884 { &hf_command_element_shutdown_ip_index,
2885 {"Command Element Shutdown IP", "wccp.command_element_shutdown_ip_Address.index", FT_UINT32, BASE_HEX, NULL, 0x0,
2886 NULL, HFILL }
2888 { &hf_command_element_shutdown_ipv4,
2889 {"Command Element Shutdown IP", "wccp.command_element_shutdown_ip_address.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
2890 NULL, HFILL }
2892 { &hf_command_element_shutdown_ipv6,
2893 {"Command Element Shutdown IP", "wccp.command_element_shutdown_ip_address.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
2894 NULL, HFILL }
2896 { &hf_command_unknown,
2897 {"Unknown Command", "wccp.command_unknown", FT_NONE, BASE_NONE, NULL, 0x0,
2898 NULL, HFILL }
2900 { &hf_service_info_type,
2901 { "Service Type", "wccp.service_info_type", FT_UINT8, BASE_DEC, VALS(service_type_vals), 0x0,
2902 NULL, HFILL }
2904 { &hf_service_info_id_standard,
2905 { "WCCP Service ID (Standard)", "wccp.service_info_std_id", FT_UINT8, BASE_DEC, VALS(service_id_vals) , 0x0,
2906 "The WCCP Service id (Standard)", HFILL }
2908 { &hf_service_info_id_dynamic,
2909 { "WCCP Service ID ( Dynamic)", "wccp.service_info_dyn_id", FT_UINT8, BASE_DEC, NULL , 0x0,
2910 "The WCCP Service id (Dynamic)", HFILL }
2912 { &hf_service_info_priority,
2913 { "Priority (highest is 255)", "wccp.service_info_priority", FT_UINT8, BASE_DEC, NULL, 0x0,
2914 NULL, HFILL }
2916 { &hf_service_info_protocol,
2917 { "Protocol", "wccp.service_info_protocol", FT_UINT8, BASE_DEC | BASE_EXT_STRING, &ipproto_val_ext, 0x0,
2918 NULL, HFILL }
2920 { &hf_service_info_flags,
2921 { "Flags", "wccp.service_info_flags", FT_UINT32, BASE_HEX, 0x0, 0x0,
2922 NULL, HFILL }
2924 { &hf_service_info_flags_src_ip_hash,
2925 { "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,
2926 NULL, HFILL }
2928 { &hf_service_info_flags_dest_ip_hash,
2929 { "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,
2930 NULL, HFILL }
2932 { &hf_service_info_flags_src_port_hash,
2933 { "Source port in primary hash", "wccp.service_info_flag.src_port_hash", FT_BOOLEAN, 32, TFS(&tfs_used_notused), WCCP2_SI_SRC_PORT_HASH,
2934 NULL, HFILL }
2936 { &hf_service_info_flags_dest_port_hash,
2937 { "Destination port in primary hash", "wccp.service_info_flag.dest_port_hash", FT_BOOLEAN, 32, TFS(&tfs_used_notused), WCCP2_SI_DST_PORT_HASH,
2938 NULL, HFILL }
2940 { &hf_service_info_flags_ports_defined,
2941 { "Ports", "wccp.service_info_flag.ports_defined", FT_BOOLEAN, 32, TFS(&tfs_defined_not_defined), WCCP2_SI_PORTS_DEFINED,
2942 NULL, HFILL }
2944 { &hf_service_info_flags_ports_source,
2945 { "Ports refer to", "wccp.service_info_flag.ports_source", FT_BOOLEAN, 32, TFS(&tfs_src_dest_port), WCCP2_SI_PORTS_SOURCE,
2946 NULL, HFILL }
2948 { &hf_service_info_flags_redirect_only_protocol_0,
2949 { "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,
2950 NULL, HFILL }
2952 { &hf_service_info_flags_src_ip_alt_hash,
2953 { "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,
2954 NULL, HFILL }
2956 { &hf_service_info_flags_dest_ip_alt_hash,
2957 { "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,
2958 NULL, HFILL }
2960 { &hf_service_info_flags_src_port_alt_hash,
2961 { "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,
2962 NULL, HFILL }
2964 { &hf_service_info_flags_dest_port_alt_hash,
2965 { "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,
2966 NULL, HFILL }
2968 { &hf_service_info_flags_reserved,
2969 { "Reserved, should be 0", "wccp.service_info_flag.reserved", FT_UINT32, BASE_HEX, NULL, 0xFFFFF000,
2970 NULL, HFILL }
2972 { &hf_service_info_source_port,
2973 { "Source Port", "wccp.service_info_source_port", FT_UINT16, BASE_DEC, NULL, 0x0,
2974 NULL, HFILL }
2976 { &hf_service_info_destination_port,
2977 { "Destination Port", "wccp.service_info_destination_port", FT_UINT16, BASE_DEC, NULL, 0x0,
2978 NULL, HFILL }
2980 { &hf_router_identity_ip_index,
2981 { "IP Address", "wccp.router_identity.ip_address.index", FT_UINT32, BASE_HEX, NULL, 0x0,
2982 NULL, HFILL }
2984 { &hf_router_identity_ipv4,
2985 { "IP Address", "wccp.router_identity.ip_address.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
2986 NULL, HFILL }
2988 { &hf_router_identity_ipv6,
2989 { "IP Address", "wccp.router_identity.ip_address.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
2990 NULL, HFILL }
2992 { &hf_router_identity_receive_id,
2993 { "Received ID", "wccp.router_identity.receive_id", FT_UINT32, BASE_DEC, 0x0, 0x0,
2994 NULL, HFILL }
2996 { &hf_router_identity_send_to_ip_index,
2997 { "Sent To IP Address", "wccp.router_identity.send_to_ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
2998 NULL, HFILL }
3000 { &hf_router_identity_send_to_ipv4,
3001 { "Sent To IP Address", "wccp.router_identity.send_to_ip.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3002 NULL, HFILL }
3004 { &hf_router_identity_send_to_ipv6,
3005 { "Sent To IP Address", "wccp.router_identity.send_to_ip.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3006 NULL, HFILL }
3008 { &hf_router_identity_received_from_num,
3009 { "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 NULL, HFILL }
3012 { &hf_web_cache_identity_index,
3013 { "Web-Cache IP Address", "wccp.web_cache_identity.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3014 NULL, HFILL }
3016 { &hf_web_cache_identity_ipv4,
3017 { "Web-Cache IP Address", "wccp.web_cache_identity.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3018 NULL, HFILL }
3020 { &hf_web_cache_identity_ipv6,
3021 { "Web-Cache IP Address", "wccp.web_cache_identity.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3022 NULL, HFILL }
3024 { &hf_web_cache_identity_hash_rev,
3025 { "Hash Revision", "wccp.web_cache_identity.hash_rev", FT_UINT16, BASE_DEC, NULL, 0x0,
3026 NULL, HFILL }
3028 { &hf_web_cache_identity_flags,
3029 { "Flags", "wccp.web_cache_identity.flags", FT_UINT16, BASE_HEX, NULL, 0x0,
3030 NULL, HFILL }
3032 { &hf_web_cache_identity_flag_hash_info,
3033 { "Hash information", "wccp.web_cache_identity.flags.hash_info", FT_BOOLEAN, 16,
3034 TFS(&tfs_historical_current), 0x1,
3035 NULL, HFILL }
3037 { &hf_web_cache_identity_flag_assign_type,
3038 { "Assignment Type", "wccp.web_cache_identity.flags.assign_type", FT_UINT16, BASE_HEX,
3039 VALS(wccp_web_cache_assignment_data_type_val), 0x6,
3040 NULL, HFILL }
3042 { &hf_web_cache_identity_flag_version_request,
3043 { "Version Request", "wccp.web_cache_identity.flags.version_request", FT_BOOLEAN, 16,
3044 TFS(&tfs_version_min_max), 0x8,
3045 NULL, HFILL }
3047 { &hf_web_cache_identity_flag_reserved,
3048 { "Reserved, should be 0", "wccp.web_cache_identity.flags.reserved", FT_UINT16, BASE_HEX,
3049 NULL, 0xFFF0,
3050 NULL, HFILL }
3052 { &hf_mask_value_set_element_value_element_num,
3053 { "Number of Value Elements", "wccp.mask_value_set_element.value_element_num", FT_UINT32, BASE_DEC, 0x0, 0x0,
3054 NULL, HFILL }
3056 { &hf_assignment_weight,
3057 { "Assignment Weight", "wccp.assignment_weight", FT_UINT16, BASE_DEC, NULL, 0x0,
3058 NULL, HFILL }
3060 { &hf_assignment_status,
3061 { "Status", "wccp.assignment_status", FT_UINT16, BASE_HEX, NULL, 0x0,
3062 NULL, HFILL }
3064 { &hf_assignment_key_ip_index,
3065 { "Assignment Key IP Address", "wccp.assignment_key.ip_index", FT_UINT32, BASE_HEX, NULL, 0x0,
3066 NULL, HFILL }
3068 { &hf_assignment_key_ipv4,
3069 { "Assignment Key IP Address", "wccp.assignment_key.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3070 NULL, HFILL }
3072 { &hf_assignment_key_ipv6,
3073 { "Assignment Key IP Address", "wccp.assignment_key.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3074 NULL, HFILL }
3076 { &hf_assignment_key_change_num,
3077 { "Assignment Key Change Number", "wccp.assignment_key.change_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3078 NULL, HFILL }
3080 { &hf_assignment_no_data,
3081 { "No Assignment Data Present", "wccp.assignment_no_data", FT_NONE, BASE_NONE, NULL, 0x0,
3082 NULL, HFILL }
3084 { &hf_router_view_member_change_num,
3085 { "Member Change Number", "wccp.router_view.member_change_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3086 NULL, HFILL }
3088 { &hf_router_router_num,
3089 { "Number of Routers", "wccp.router_view.router_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3090 NULL, HFILL }
3092 { &hf_router_identity_router_ip_index,
3093 { "Router IP Address", "wccp.router_identity.router_ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3094 NULL, HFILL }
3096 { &hf_router_identity_router_ipv4,
3097 { "Router IP Address", "wccp.router_identity.router_ip.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3098 NULL, HFILL }
3100 { &hf_router_identity_router_ipv6,
3101 { "Router IP Address", "wccp.router_identity.router_ip.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3102 NULL, HFILL }
3104 { &hf_router_identity_received_from_ip_index,
3105 { "Received From IP Address/Target Web Cache IP", "wccp.router_identity.received_from_ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3106 NULL, HFILL }
3108 { &hf_router_identity_received_from_ipv4,
3109 { "Received From IP Address/Target Web Cache IP", "wccp.router_identity.received_from_ip.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3110 NULL, HFILL }
3112 { &hf_router_identity_received_from_ipv6,
3113 { "Received From IP Address/Target Web Cache IP", "wccp.router_identity.received_from_ip.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3114 NULL, HFILL }
3116 { &hf_wc_view_info_change_num,
3117 { "Change Number", "wccp.wc_view_info.change_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3118 NULL, HFILL }
3120 { &hf_wc_view_info_router_ip_index,
3121 { "Router IP", "wccp.wc_view_info.router_ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3122 NULL, HFILL }
3124 { &hf_wc_view_info_router_ipv4,
3125 { "Router IP", "wccp.wc_view_info.router_ip.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3126 NULL, HFILL }
3128 { &hf_wc_view_info_router_ipv6,
3129 { "Router IP", "wccp.wc_view_info.router_ip.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3130 NULL, HFILL }
3132 { &hf_wc_view_info_wc_ip_index,
3133 { "Web Cache IP", "wccp.wc_view_info.wc_ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3134 NULL, HFILL }
3136 { &hf_wc_view_info_wc_ipv4,
3137 { "Web Cache IP", "wccp.wc_view_info.wc_ip.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3138 NULL, HFILL }
3140 { &hf_wc_view_info_wc_ipv6,
3141 { "Web Cache IP", "wccp.wc_view_info.wc_ip.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3142 NULL, HFILL }
3144 { &hf_wc_view_router_num,
3145 { "Number of Routers", "wccp.wc_view_info.router_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3146 NULL, HFILL }
3148 { &hf_wc_view_wc_num,
3149 { "Number of Web Caches", "wccp.wc_view_info.wc_num", FT_UINT32, BASE_DEC, 0x0, 0x0,
3150 NULL, HFILL }
3152 { &hf_wc_identity_ip_address_index,
3153 { "Web Cache Identity", "wccp.wc_identity_ip_address.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3154 "The IP identifying the Web Cache", HFILL }
3156 { &hf_wc_identity_ip_address_ipv4,
3157 { "Web Cache Identity", "wccp.wc_identity_ip_address.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3158 "The IP identifying the Web Cache", HFILL }
3160 { &hf_wc_identity_ip_address_ipv6,
3161 { "Web Cache Identity", "wccp.wc_identity_ip_address.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3162 "The IP identifying the Web Cache", HFILL }
3164 { &hf_router_assignment_element_change_num,
3165 { "Change Number", "wccp.router_assignment_element.change_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3166 NULL, HFILL }
3168 { &hf_assignment_info_router_num,
3169 { "Number of Routers", "wccp.assignment_info.router_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3170 NULL, HFILL }
3172 { &hf_assignment_info_router_ip_index,
3173 { "Router IP", "wccp.assignment_info.router_ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3174 NULL, HFILL }
3176 { &hf_assignment_info_router_ipv4,
3177 { "Router IP", "wccp.assignment_info.router_ip.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3178 NULL, HFILL }
3180 { &hf_assignment_info_router_ipv6,
3181 { "Router IP", "wccp.assignment_info.router_ip.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3182 NULL, HFILL }
3184 { &hf_hash_buckets_assignment_wc_num,
3185 { "Number of WC", "wccp.hash_buckets_assignment.wc_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3186 NULL, HFILL }
3188 { &hf_hash_buckets_assignment_wc_ip_index,
3189 { "WC IP", "wccp.hash_buckets_assignment.wc_ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3190 NULL, HFILL }
3192 { &hf_hash_buckets_assignment_wc_ipv4,
3193 { "WC IP", "wccp.hash_buckets_assignment.wc_ip.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3194 NULL, HFILL }
3196 { &hf_hash_buckets_assignment_wc_ipv6,
3197 { "WC IP", "wccp.hash_buckets_assignment.wc_ip.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3198 NULL, HFILL }
3200 { &hf_router_view_ip_index,
3201 { "Router IP Address", "wccp.router_view.ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3202 NULL, HFILL }
3204 { &hf_router_view_ipv4,
3205 { "Router IP Address", "wccp.router_view.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3206 NULL, HFILL }
3208 { &hf_router_view_ipv6,
3209 { "Router IP Address", "wccp.router_view.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3210 NULL, HFILL }
3212 { &hf_router_query_info_ip_index,
3213 { "Web-Cache Identity Element IP address", "wccp.router_query_info.ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3214 NULL, HFILL }
3216 { &hf_router_query_info_ipv4,
3217 { "Web-Cache Identity Element IP address", "wccp.router_query_info.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3218 NULL, HFILL }
3220 { &hf_router_query_info_ipv6,
3221 { "Web-Cache Identity Element IP address", "wccp.router_query_info.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3222 NULL, HFILL }
3224 { &hf_router_query_info_send_to_ip_index,
3225 { "Sent To IP Address", "wccp.router_query_info.send_to_ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3226 NULL, HFILL }
3228 { &hf_router_query_info_send_to_ipv4,
3229 { "Sent To IP Address", "wccp.router_query_info.send_to_ip.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3230 NULL, HFILL }
3232 { &hf_router_query_info_send_to_ipv6,
3233 { "Sent To IP Address", "wccp.router_query_info.send_to_ip.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3234 NULL, HFILL }
3236 { &hf_router_query_info_target_ip_index,
3237 { "Target IP Address", "wccp.router_query_info.target_ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3238 NULL, HFILL }
3240 { &hf_router_query_info_target_ipv4,
3241 { "Target IP Address", "wccp.router_query_info.target_ip.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3242 NULL, HFILL }
3244 { &hf_router_query_info_target_ipv6,
3245 { "Target IP Address", "wccp.router_query_info.target_ip.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3246 NULL, HFILL }
3248 { &hf_capability_element_type,
3249 { "Type", "wccp.capability_element.type", FT_UINT16, BASE_DEC, VALS(capability_type_vals), 0x0,
3250 NULL, HFILL }
3252 { &hf_capability_element_length,
3253 { "Value Length", "wccp.capability_element.length", FT_UINT16, BASE_DEC, NULL, 0x0,
3254 NULL, HFILL }
3256 { &hf_capability_info_value,
3257 { "Value", "wccp.capability_info.value", FT_UINT32, BASE_HEX, NULL, 0x0,
3258 NULL, HFILL }
3260 { &hf_capability_forwarding_method_flag_gre,
3261 { "GRE-encapsulated", "wccp.capability_info.forwarding_method_flag.gre", FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), WCCP2_FORWARDING_METHOD_GRE,
3262 NULL, HFILL }
3264 { &hf_capability_forwarding_method_flag_l2,
3265 { "L2 rewrite", "wccp.capability_info.forwarding_method_flag.l2", FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), WCCP2_FORWARDING_METHOD_L2,
3266 NULL, HFILL }
3268 { &hf_capability_assignment_method_flag_hash,
3269 { "Hash", "wccp.capability_info.assignment_method_flag.hash", FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), WCCP2_ASSIGNMENT_METHOD_HASH,
3270 NULL, HFILL }
3272 { &hf_capability_assignment_method_flag_mask,
3273 { "Mask", "wccp.capability_info.assignment_method_flag.mask", FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), WCCP2_ASSIGNMENT_METHOD_MASK,
3274 NULL, HFILL }
3276 { &hf_capability_return_method_flag_gre,
3277 { "GRE-encapsulated", "wccp.capability_info.return_method_flag.gre", FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), WCCP2_PACKET_RETURN_METHOD_GRE,
3278 NULL, HFILL }
3280 { &hf_capability_return_method_flag_l2,
3281 { "L2 rewrite", "wccp.capability_info.return_method_flag.l2", FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), WCCP2_PACKET_RETURN_METHOD_L2,
3282 NULL, HFILL }
3284 { &hf_capability_transmit_t,
3285 { "Message interval in milliseconds", "wccp.capability.transmit_t", FT_UINT16, BASE_DEC, NULL, 0x0,
3286 NULL, HFILL }
3288 { &hf_capability_transmit_t_upper_limit,
3289 { "Message interval upper limit in milliseconds", "wccp.capability.transmit_t.upper_limit", FT_UINT16, BASE_DEC, NULL, 0x0,
3290 NULL, HFILL }
3292 { &hf_capability_transmit_t_lower_limit,
3293 { "Message interval lower limit in milliseconds", "wccp.capability.transmit_t.lower_limit", FT_UINT16, BASE_DEC, NULL, 0x0,
3294 NULL, HFILL }
3296 { &hf_capability_timer_scale_timeout_scale,
3297 { "Timer scale", "wccp.capability.timer_scale.timeout_scale", FT_UINT8, BASE_DEC, NULL, 0x0,
3298 NULL, HFILL }
3300 { &hf_capability_timer_scale_timeout_scale_upper_limit,
3301 { "Timer scale upper limit", "wccp.capability.timer_scale.timeout_scale.upper_limit", FT_UINT8, BASE_DEC, NULL, 0x0,
3302 NULL, HFILL }
3304 { &hf_capability_timer_scale_timeout_scale_lower_limit,
3305 { "Timer scale lower limit", "wccp.capability.timer_scale.timeout_scale.lower_limit", FT_UINT8, BASE_DEC, NULL, 0x0,
3306 NULL, HFILL }
3308 { &hf_capability_timer_scale_ra_timer_scale,
3309 { "RA Timer scale", "wccp.capability.timer_scale.ra_timer_scale", FT_UINT8, BASE_DEC, NULL, 0x0,
3310 NULL, HFILL }
3312 { &hf_capability_timer_scale_ra_scale_upper_limit,
3313 { "RA Timer scale upper limit", "wccp.capability.timer_scale.ra_timer_scale.upper_limit", FT_UINT8, BASE_DEC, NULL, 0x0,
3314 NULL, HFILL }
3316 { &hf_capability_timer_scale_ra_scale_lower_limit,
3317 { "RA Timer scale lower limit", "wccp.capability.timer_scale.ra_timer_scale.lower_limit", FT_UINT8, BASE_DEC, NULL, 0x0,
3318 NULL, HFILL }
3320 { &hf_capability_value,
3321 { "Value", "wccp.capability.value", FT_BYTES, BASE_NONE, NULL, 0x0,
3322 NULL, HFILL }
3324 { &hf_reserved_zero,
3325 { "Reserved, must be 0", "wccp.reserved_zero", FT_UINT16, BASE_DEC, NULL, 0x0,
3326 NULL, HFILL }
3328 { &hf_value_element_src_ip_index,
3329 { "Source Address", "wccp.value_element.src_ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3330 NULL, HFILL }
3332 { &hf_value_element_src_ipv4,
3333 { "Source Address", "wccp.value_element.src_ip.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3334 NULL, HFILL }
3336 { &hf_value_element_src_ipv6,
3337 { "Source Address", "wccp.value_element.src_ip.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3338 NULL, HFILL }
3340 { &hf_value_element_dest_ip_index,
3341 { "Destination Address", "wccp.value_element.dest_ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3342 NULL, HFILL }
3344 { &hf_value_element_dest_ipv4,
3345 { "Destination Address", "wccp.value_element.dest_ip.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3346 NULL, HFILL }
3348 { &hf_value_element_dest_ipv6,
3349 { "Destination Address", "wccp.value_element.dest_ip.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3350 NULL, HFILL }
3352 { &hf_value_element_src_port,
3353 { "Source Port", "wccp.value_element.src_port", FT_UINT16, BASE_DEC, NULL, 0x0,
3354 NULL, HFILL }
3356 { &hf_value_element_dest_port,
3357 { "Destination Port", "wccp.value_element.dest_port", FT_UINT16, BASE_DEC, NULL, 0x0,
3358 NULL, HFILL }
3360 { &hf_value_element_web_cache_ip_index,
3361 { "Web Cache Address", "wccp.value_element.web_cache_ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3362 NULL, HFILL }
3364 { &hf_value_element_web_cache_ipv4,
3365 { "Web Cache Address", "wccp.value_element.web_cache_ip.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3366 NULL, HFILL }
3368 { &hf_value_element_web_cache_ipv6,
3369 { "Web Cache Address", "wccp.value_element.web_cache_ip.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3370 NULL, HFILL }
3372 { &hf_mask_value_set_list_num_elements,
3373 { "Number of elements", "wccp.mask_value_set_list.num_elements", FT_UINT32, BASE_DEC, NULL, 0x0,
3374 NULL, HFILL }
3376 { &hf_mask_element_src_ip,
3377 { "Source Address Mask", "wccp.mask_element.src_ip", FT_UINT32, BASE_HEX, NULL, 0x0,
3378 NULL, HFILL }
3380 { &hf_mask_element_dest_ip,
3381 { "Destination Address Mask", "wccp.mask_element.dest_ip", FT_UINT32, BASE_HEX, NULL, 0x0,
3382 NULL, HFILL }
3384 { &hf_mask_element_src_port,
3385 { "Source Port Mask", "wccp.mask_element.src_port", FT_UINT16, BASE_HEX, NULL, 0x0,
3386 NULL, HFILL }
3388 { &hf_mask_element_dest_port,
3389 { "Destination Port Mask", "wccp.mask_element.dest_port", FT_UINT16, BASE_HEX, NULL, 0x0,
3390 NULL, HFILL }
3392 { &hf_alt_assignment_info_assignment_type,
3393 { "Assignment type", "wccp.alt_assignment_info.assignment_type", FT_UINT16, BASE_DEC, VALS(assignment_type_vals), 0x0,
3394 NULL, HFILL }
3396 { &hf_extended_assignment_data_type,
3397 { "Assignment type", "wccp.extended_assignment_data.type", FT_UINT16, BASE_DEC, VALS(assignment_type_vals), 0x0,
3398 NULL, HFILL }
3400 { &hf_alt_assignment_map_assignment_type,
3401 { "Assignment type", "wccp.alt_assignment_map.assignment_type", FT_UINT16, BASE_DEC, VALS(assignment_type_vals), 0x0,
3402 NULL, HFILL }
3404 { &hf_alt_assignment_map_assignment_length,
3405 { "Assignment length", "wccp.alt_assignment_map.assignment_length", FT_UINT16, BASE_DEC, NULL, 0x0,
3406 NULL, HFILL }
3408 { &hf_alt_assignment_info_assignment_length,
3409 { "Assignment length", "wccp.alt_assignment_info.assignment_length", FT_UINT16, BASE_DEC, NULL, 0x0,
3410 NULL, HFILL }
3412 { &hf_extended_assignment_data_length,
3413 { "Assignment length", "wccp.extended_assignment_data.length", FT_UINT16, BASE_DEC, NULL, 0x0,
3414 NULL, HFILL }
3416 { &hf_alt_assignment_info_num_routers,
3417 { "Number of routers", "wccp.alt_assignment_info.num_routers", FT_UINT32, BASE_DEC, NULL, 0x0,
3418 NULL, HFILL }
3420 { &hf_alt_assignment_mask_value_set_element_num_wc_value_elements,
3421 { "Number of Web-Cache Value Elements", "wccp.alt_assignment_mask_value_set_element.num_wc_value_elements", FT_UINT32, BASE_DEC, NULL, 0x0,
3422 NULL, HFILL }
3424 { &hf_web_cache_value_element_wc_address_index,
3425 { "Web-Cache Address", "wccp.web_cache_value_element.wc_address.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3426 NULL, HFILL }
3428 { &hf_web_cache_value_element_wc_address_ipv4,
3429 { "Web-Cache Address", "wccp.web_cache_value_element.wc_address.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3430 NULL, HFILL }
3432 { &hf_web_cache_value_element_wc_address_ipv6,
3433 { "Web-Cache Address", "wccp.web_cache_value_element.wc_address.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3434 NULL, HFILL }
3436 { &hf_web_cache_value_element_num_values,
3437 { "Number of Value Sequence Numbers", "wccp.web_cache_value_element.num_values", FT_UINT32, BASE_DEC, NULL, 0x0,
3438 NULL, HFILL }
3440 { &hf_web_cache_value_seq_num,
3441 { "Value Sequence Number", "wccp.web_cache_value_element.value_seq_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3442 NULL, HFILL }
3444 { &hf_alt_assignment_mask_value_set_list_num_elements,
3445 { "Number of Alternate Mask/Value Set Elements", "wccp.alt_assignment_mask_value_list.num_elements", FT_UINT32, BASE_DEC, NULL, 0x0,
3446 NULL, HFILL }
3448 { &hf_address_table_family,
3449 { "Family Type", "wccp.address_table.family_type", FT_UINT16, BASE_DEC, VALS(wccp_address_family_val), 0x0,
3450 "The WCCP Address Table Family type", HFILL }
3452 { &hf_address_table_address_length,
3453 { "Address Length", "wccp.address_table.address_length", FT_UINT16, BASE_DEC, NULL, 0x0,
3454 "The WCCP Address Table Address Length", HFILL }
3456 { &hf_address_table_length,
3457 { "Length", "wccp.address_table.length", FT_UINT32, BASE_DEC, NULL, 0x0,
3458 "The WCCP Address Table Length", HFILL }
3460 { &hf_address_table_element,
3461 { "Address", "wccp.address_table.element", FT_STRING, BASE_NONE, NULL, 0x0,
3462 NULL, HFILL }
3466 static int *ett[] = {
3467 &ett_wccp,
3468 &ett_buckets,
3469 &ett_hash_assignment_buckets,
3470 &ett_mask_assignment_data_element,
3471 &ett_alternate_mask_assignment_data_element,
3472 &ett_extended_assigment_data_element,
3473 &ett_table_element,
3474 &ett_hash_flags,
3475 &ett_wc_identity_flags,
3476 &ett_cache_info,
3477 &ett_security_info,
3478 &ett_service_info,
3479 &ett_service_flags,
3480 &ett_service_info_ports,
3481 &ett_wc_view_info_router_element,
3482 &ett_router_identity_info,
3483 &ett_wc_identity_element,
3484 &ett_wc_identity_info,
3485 &ett_router_view_info,
3486 &ett_wc_view_info,
3487 &ett_router_assignment_element,
3488 &ett_hash_buckets_assignment_wc_element,
3489 &ett_hash_buckets_assignment_buckets,
3490 &ett_router_alt_assignment_element,
3491 &ett_router_assignment_info,
3492 &ett_query_info,
3493 &ett_capabilities_info,
3494 &ett_capability_element,
3495 &ett_capability_forwarding_method,
3496 &ett_capability_assignment_method,
3497 &ett_capability_return_method,
3498 &ett_capability_transmit_t,
3499 &ett_capability_timer_scale,
3500 &ett_alt_assignment_info,
3501 &ett_alt_assignment_map,
3502 &ett_address_table,
3503 &ett_assignment_map,
3504 &ett_command_extension,
3505 &ett_alternate_mask_value_set,
3506 &ett_alternate_mask_value_set_element,
3507 &ett_mv_set_list,
3508 &ett_mv_set_element,
3509 &ett_mv_set_value_list,
3510 &ett_alternate_mv_set_element_list,
3511 &ett_web_cache_value_element_list,
3512 &ett_alternate_mv_set_element,
3513 &ett_value_element,
3514 &ett_unknown_info,
3517 static ei_register_info ei[] = {
3518 { &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 }},
3519 { &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 }},
3520 { &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 }},
3521 { &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 }},
3522 { &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 }},
3523 { &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 }},
3524 { &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 }},
3525 { &ei_wccp_missing_assignment, { "wccp.missing.assignment", PI_PROTOCOL, PI_ERROR, "This message should contain a Alternate Assignment, Assignment Map, Assignment Info or "
3526 "Alternative Assignment Map component, but it is missing", EXPFILL }},
3527 { &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 }},
3528 { &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 }},
3529 { &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 }},
3530 { &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 }},
3531 { &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 }},
3532 { &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 }},
3533 { &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 }},
3534 { &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 }},
3535 { &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 }},
3536 { &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 }},
3537 { &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 }},
3538 { &ei_wccp_assignment_length_bad, { "wccp.assignment_length_bad", PI_PROTOCOL, PI_ERROR, "Assignment length bad", EXPFILL }},
3539 { &ei_wccp_length_bad, { "wccp.length_bad", PI_PROTOCOL, PI_ERROR, "Length bad", EXPFILL }},
3540 { &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 }},
3541 { &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 }},
3542 { &ei_wccp_router_identity_receive_id_zero, { "wccp.router_identity.receive_id.zero", PI_PROTOCOL, PI_WARN, "Receive ID shouldn't be 0", EXPFILL }},
3543 { &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 }},
3544 { &ei_wccp_address_table_family_unknown, { "wccp.address_table.family_type.unknown", PI_PROTOCOL, PI_ERROR, "Unknown address family", EXPFILL }},
3545 { &ei_wccp_capability_element_length, { "wccp.capability_element.length.invalid", PI_PROTOCOL, PI_WARN, "Value Length invalid", EXPFILL }},
3546 { &ei_wccp_port_fields_not_used, { "wccp.port_fields_not_used", PI_PROTOCOL, PI_NOTE, "Ports fields not used", EXPFILL }},
3547 { &ei_wccp_a_zero_not_c, { "wccp.a_zero_not_c", PI_PROTOCOL, PI_WARN, "Error A is 0, but C is not", EXPFILL }},
3548 #if 0
3549 { &ei_wccp_c_zero_not_a, { "wccp.c_zero_not_a", PI_PROTOCOL, PI_WARN, "Error C is 0, but A is not", EXPFILL }},
3550 #endif
3553 expert_module_t* expert_wccp;
3555 proto_wccp = proto_register_protocol("Web Cache Communication Protocol",
3556 "WCCP", "wccp");
3557 proto_register_field_array(proto_wccp, hf, array_length(hf));
3558 proto_register_subtree_array(ett, array_length(ett));
3559 expert_wccp = expert_register_protocol(proto_wccp);
3560 expert_register_field_array(expert_wccp, ei, array_length(ei));
3561 wccp_handle = register_dissector("wccp", dissect_wccp, proto_wccp);
3564 void
3565 proto_reg_handoff_wccp(void)
3567 dissector_add_uint_with_preference("udp.port", UDP_PORT_WCCP, wccp_handle);
3571 * Editor modelines - https://www.wireshark.org/tools/modelines.html
3573 * Local variables:
3574 * c-basic-offset: 2
3575 * tab-width: 8
3576 * indent-tabs-mode: nil
3577 * End:
3579 * vi: set shiftwidth=2 tabstop=8 expandtab:
3580 * :indentSize=2:tabSize=8:noTabs=true: