Coverage Report

Created: 2026-11-12 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-wccp.c
Line
Count
Source
1
/* packet-wccp.c
2
 * Routines for Web Cache C* Protocol dissection
3
 * Jerry Talkington <jtalkington@users.sourceforge.net>
4
 *
5
 * https://datatracker.ietf.org/doc/html/draft-mclaggan-wccp-v2rev1-00
6
 *
7
 * Wireshark - Network traffic analyzer
8
 * By Gerald Combs <gerald@wireshark.org>
9
 * Copyright 1998 Gerald Combs
10
 *
11
 * SPDX-License-Identifier: GPL-2.0-or-later
12
 */
13
14
#include "config.h"
15
16
#include <epan/packet.h>
17
#include <epan/to_str.h>
18
#include <epan/expert.h>
19
#include <epan/tfs.h>
20
#include <epan/iana-info.h>
21
#include <wsutil/array.h>
22
#include <wsutil/ws_roundup.h>
23
#include "packet-wccp.h"
24
25
void proto_register_wccp(void);
26
void proto_reg_handoff_wccp(void);
27
28
static dissector_handle_t wccp_handle;
29
30
static int proto_wccp;
31
static int hf_wccp_message_type;   /* the message type */
32
static int hf_wccp_version;        /* protocol version */
33
static int hf_bucket;
34
static int hf_bucket_bit;
35
static int hf_message_header_version;
36
static int hf_hash_revision;       /* the version of the hash */
37
static int hf_change_num;          /* change number */
38
static int hf_hash_flag;
39
static int hf_hash_flag_u;
40
static int hf_recvd_id;
41
static int hf_wc_num;
42
static int hf_wc_view_wc_num;
43
static int hf_cache_ip;
44
static int hf_message_header_length;
45
static int hf_item_type;
46
static int hf_item_length;
47
static int hf_item_data;
48
static int hf_security_info_option;
49
static int hf_security_info_md5_checksum;
50
static int hf_command_element_type;
51
static int hf_command_element_length;
52
static int hf_command_length;
53
static int hf_command_element_shutdown_ip_index;
54
static int hf_command_element_shutdown_ipv4;
55
static int hf_command_element_shutdown_ipv6;
56
static int hf_command_unknown;
57
static int hf_service_info_type;
58
static int hf_service_info_id_standard;
59
static int hf_service_info_id_dynamic;
60
static int hf_service_info_priority;
61
static int hf_service_info_protocol;
62
static int hf_service_info_flags;
63
static int hf_service_info_flags_src_ip_hash;
64
static int hf_service_info_flags_dest_ip_hash;
65
static int hf_service_info_flags_src_port_hash;
66
static int hf_service_info_flags_dest_port_hash;
67
static int hf_service_info_flags_ports_defined;
68
static int hf_service_info_flags_ports_source;
69
static int hf_service_info_flags_redirect_only_protocol_0;
70
static int hf_service_info_flags_src_ip_alt_hash;
71
static int hf_service_info_flags_dest_ip_alt_hash;
72
static int hf_service_info_flags_src_port_alt_hash;
73
static int hf_service_info_flags_dest_port_alt_hash;
74
static int hf_service_info_flags_reserved;
75
static int hf_service_info_source_port;
76
static int hf_service_info_destination_port;
77
static int hf_router_identity_ip_index;
78
static int hf_router_identity_ipv4;
79
static int hf_router_identity_ipv6;
80
static int hf_router_identity_receive_id;
81
static int hf_router_identity_send_to_ip_index;
82
static int hf_router_identity_send_to_ipv4;
83
static int hf_router_identity_send_to_ipv6;
84
static int hf_router_identity_received_from_num;
85
static int hf_web_cache_identity_index;
86
static int hf_web_cache_identity_ipv4;
87
static int hf_web_cache_identity_ipv6;
88
static int hf_web_cache_identity_hash_rev;
89
static int hf_web_cache_identity_flags;
90
static int hf_web_cache_identity_flag_hash_info;
91
static int hf_web_cache_identity_flag_assign_type;
92
static int hf_web_cache_identity_flag_version_request;
93
static int hf_web_cache_identity_flag_reserved;
94
static int hf_mask_value_set_element_value_element_num;
95
static int hf_assignment_weight;
96
static int hf_assignment_status;
97
static int hf_assignment_key_ip_index;
98
static int hf_assignment_key_ipv4;
99
static int hf_assignment_key_ipv6;
100
static int hf_assignment_key_change_num;
101
static int hf_assignment_no_data;
102
static int hf_router_view_member_change_num;
103
static int hf_router_router_num;
104
static int hf_router_identity_router_ip_index;
105
static int hf_router_identity_router_ipv4;
106
static int hf_router_identity_router_ipv6;
107
static int hf_wc_view_info_change_num;
108
static int hf_wc_view_info_router_ip_index;
109
static int hf_wc_view_info_router_ipv4;
110
static int hf_wc_view_info_router_ipv6;
111
static int hf_wc_view_info_wc_ip_index;
112
static int hf_wc_view_info_wc_ipv4;
113
static int hf_wc_view_info_wc_ipv6;
114
static int hf_wc_view_router_num;
115
static int hf_wc_identity_ip_address_index;
116
static int hf_wc_identity_ip_address_ipv4;
117
static int hf_wc_identity_ip_address_ipv6;
118
static int hf_router_identity_received_from_ip_index;
119
static int hf_router_identity_received_from_ipv4;
120
static int hf_router_identity_received_from_ipv6;
121
static int hf_router_assignment_element_change_num;
122
static int hf_assignment_info_router_num;
123
static int hf_hash_buckets_assignment_wc_num;
124
static int hf_hash_buckets_assignment_wc_ip_index;
125
static int hf_hash_buckets_assignment_wc_ipv4;
126
static int hf_hash_buckets_assignment_wc_ipv6;
127
static int hf_assignment_info_router_ip_index;
128
static int hf_assignment_info_router_ipv4;
129
static int hf_assignment_info_router_ipv6;
130
static int hf_router_view_ip_index;
131
static int hf_router_view_ipv4;
132
static int hf_router_view_ipv6;
133
static int hf_router_query_info_ip_index;
134
static int hf_router_query_info_ipv4;
135
static int hf_router_query_info_ipv6;
136
static int hf_router_query_info_send_to_ip_index;
137
static int hf_router_query_info_send_to_ipv4;
138
static int hf_router_query_info_send_to_ipv6;
139
static int hf_router_query_info_target_ip_index;
140
static int hf_router_query_info_target_ipv4;
141
static int hf_router_query_info_target_ipv6;
142
static int hf_capability_element_type;
143
static int hf_capability_element_length;
144
static int hf_capability_info_value;
145
static int hf_capability_forwarding_method_flag_gre;
146
static int hf_capability_forwarding_method_flag_l2;
147
static int hf_capability_assignment_method_flag_hash;
148
static int hf_capability_assignment_method_flag_mask;
149
static int hf_capability_return_method_flag_gre;
150
static int hf_capability_return_method_flag_l2;
151
static int hf_capability_transmit_t;
152
static int hf_capability_transmit_t_upper_limit;
153
static int hf_capability_transmit_t_lower_limit;
154
static int hf_capability_timer_scale_timeout_scale;
155
static int hf_capability_timer_scale_ra_timer_scale;
156
static int hf_capability_timer_scale_timeout_scale_upper_limit;
157
static int hf_capability_timer_scale_timeout_scale_lower_limit;
158
static int hf_capability_timer_scale_ra_scale_upper_limit;
159
static int hf_capability_timer_scale_ra_scale_lower_limit;
160
static int hf_capability_value;
161
static int hf_reserved_zero;
162
static int hf_value_element_src_ip_index;
163
static int hf_value_element_src_ipv4;
164
static int hf_value_element_src_ipv6;
165
static int hf_value_element_dest_ip_index;
166
static int hf_value_element_dest_ipv4;
167
static int hf_value_element_dest_ipv6;
168
static int hf_value_element_src_port;
169
static int hf_value_element_dest_port;
170
static int hf_value_element_web_cache_ip_index;
171
static int hf_value_element_web_cache_ipv4;
172
static int hf_value_element_web_cache_ipv6;
173
static int hf_mask_value_set_list_num_elements;
174
static int hf_mask_element_src_ip;
175
static int hf_mask_element_dest_ip;
176
static int hf_mask_element_src_port;
177
static int hf_mask_element_dest_port;
178
static int hf_alt_assignment_info_assignment_type;
179
static int hf_extended_assignment_data_type;
180
static int hf_alt_assignment_info_assignment_length;
181
static int hf_alt_assignment_map_assignment_type;
182
static int hf_alt_assignment_map_assignment_length;
183
static int hf_extended_assignment_data_length;
184
static int hf_alt_assignment_info_num_routers;
185
static int hf_alt_assignment_mask_value_set_element_num_wc_value_elements;
186
static int hf_web_cache_value_element_wc_address_index;
187
static int hf_web_cache_value_element_wc_address_ipv4;
188
static int hf_web_cache_value_element_wc_address_ipv6;
189
static int hf_web_cache_value_element_num_values;
190
static int hf_web_cache_value_seq_num;
191
static int hf_alt_assignment_mask_value_set_list_num_elements;
192
static int hf_address_table_family;
193
static int hf_address_table_address_length;
194
static int hf_address_table_length;
195
static int hf_address_table_element;
196
197
static int ett_wccp;
198
static int ett_buckets;
199
static int ett_hash_assignment_buckets;
200
static int ett_mask_assignment_data_element;
201
static int ett_alternate_mask_assignment_data_element;
202
static int ett_extended_assigment_data_element;
203
static int ett_table_element;
204
static int ett_hash_flags;
205
static int ett_wc_identity_flags;
206
static int ett_cache_info;
207
static int ett_security_info;
208
static int ett_service_info;
209
static int ett_service_flags;
210
static int ett_service_info_ports;
211
static int ett_wc_view_info_router_element;
212
static int ett_router_identity_info;
213
static int ett_wc_identity_element;
214
static int ett_wc_identity_info;
215
static int ett_router_view_info;
216
static int ett_wc_view_info;
217
static int ett_router_assignment_element;
218
static int ett_hash_buckets_assignment_wc_element;
219
static int ett_hash_buckets_assignment_buckets;
220
static int ett_router_alt_assignment_element;
221
static int ett_router_assignment_info;
222
static int ett_query_info;
223
static int ett_capabilities_info;
224
static int ett_capability_element;
225
static int ett_capability_forwarding_method;
226
static int ett_capability_assignment_method;
227
static int ett_capability_return_method;
228
static int ett_capability_transmit_t;
229
static int ett_capability_timer_scale;
230
static int ett_alt_assignment_info;
231
static int ett_alt_assignment_map;
232
static int ett_address_table;
233
static int ett_assignment_map;
234
static int ett_command_extension;
235
static int ett_alternate_mask_value_set;
236
static int ett_alternate_mask_value_set_element;
237
static int ett_mv_set_list;
238
static int ett_mv_set_element;
239
static int ett_mv_set_value_list;
240
static int ett_alternate_mv_set_element_list;
241
static int ett_web_cache_value_element_list;
242
static int ett_alternate_mv_set_element;
243
static int ett_value_element;
244
static int ett_unknown_info;
245
246
static expert_field ei_wccp_missing_security_info;
247
static expert_field ei_wccp_missing_service_info;
248
static expert_field ei_wccp_missing_wc_id_info;
249
static expert_field ei_wccp_missing_router_id_info;
250
static expert_field ei_wccp_missing_query_info;
251
static expert_field ei_wccp_missing_wc_view_info;
252
static expert_field ei_wccp_missing_rtr_view_info;
253
static expert_field ei_wccp_contains_redirect_assignment;
254
static expert_field ei_wccp_contains_router_id_info;
255
static expert_field ei_wccp_contains_rtr_view_info;
256
static expert_field ei_wccp_contains_query_info;
257
static expert_field ei_wccp_contains_alt_assignment;
258
static expert_field ei_wccp_contains_assign_map;
259
static expert_field ei_wccp_contains_alt_assignment_map;
260
static expert_field ei_wccp_contains_wc_id_info;
261
static expert_field ei_wccp_contains_wc_view_info;
262
static expert_field ei_wccp_contains_capabilities_info;
263
static expert_field ei_wccp_contains_command_extension;
264
static expert_field ei_wccp_missing_assignment;
265
static expert_field ei_wccp_assignment_length_bad;
266
static expert_field ei_wccp_length_bad;
267
static expert_field ei_wccp_service_info_priority_nonzero;
268
static expert_field ei_wccp_service_info_protocol_nonzero;
269
static expert_field ei_wccp_router_identity_receive_id_zero;
270
static expert_field ei_wccp_web_cache_identity_hash_rev_zero;
271
static expert_field ei_wccp_address_table_family_unknown;
272
static expert_field ei_wccp_capability_element_length;
273
static expert_field ei_wccp_port_fields_not_used;
274
static expert_field ei_wccp_a_zero_not_c;
275
/* static expert_field ei_wccp_c_zero_not_a; */
276
277
/*
278
 * At
279
 *
280
 *      https://datatracker.ietf.org/doc/html/draft-forster-wrec-wccp-v1-00
281
 *
282
 * is the now-expired Internet-Draft for WCCP 1.0 (Web Cache Coordination
283
 * Protocol V1.0).
284
 *
285
 * At
286
 *
287
 *      https://datatracker.ietf.org/doc/html/draft-wilson-wrec-wccp-v2-01
288
 *
289
 * is the now-expired Internet-Draft for WCCP 2.0 (Web Cache Communication
290
 * Protocol V2.0).
291
 *
292
 *      https://datatracker.ietf.org/doc/html/draft-param-wccp-v2rev1-01
293
 *
294
 * is the now-expired Internet-Draft for WCCP 2.01 (Web Cache Communication
295
 * Protocol V2, Revision 1).
296
 */
297
298
/* This is NOT IANA assigned */
299
16
#define UDP_PORT_WCCP           2048
300
301
#define WCCPv1                  4
302
#define WCCPv2                  0x0200
303
#define WCCPv2r1                0x0201
304
0
#define WCCP_HERE_I_AM          7
305
1
#define WCCP_I_SEE_YOU          8
306
1
#define WCCP_ASSIGN_BUCKET      9
307
0
#define WCCP2_HERE_I_AM         10
308
0
#define WCCP2_I_SEE_YOU         11
309
12
#define WCCP2_REDIRECT_ASSIGN   12
310
0
#define WCCP2_REMOVAL_QUERY     13
311
312
static const value_string wccp_type_vals[] = {
313
  { WCCP_HERE_I_AM,        "1.0 Here I am" },
314
  { WCCP_I_SEE_YOU,        "1.0 I see you" },
315
  { WCCP_ASSIGN_BUCKET,    "1.0 Assign bucket" },
316
  { WCCP2_HERE_I_AM,       "2.0 Here I am" },
317
  { WCCP2_I_SEE_YOU,       "2.0 I see you" },
318
  { WCCP2_REDIRECT_ASSIGN, "2.0 Redirect assign" },
319
  { WCCP2_REMOVAL_QUERY,   "2.0 Removal query" },
320
  { 0,                     NULL }
321
};
322
323
static const value_string wccp_version_val[] = {
324
  { WCCPv1, "1"},
325
  { WCCPv2, "2"},
326
  { WCCPv2r1, "2.01"},
327
  { 0, NULL}
328
};
329
330
static const true_false_string tfs_src_dest_port = { "Source port", "Destination port" };
331
static const true_false_string tfs_redirect_protocol0 = { "Redirect only protocol 0 (IP)", "Redirect all traffic" };
332
static const true_false_string tfs_historical_current = { "Historical", "Current" };
333
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"};
334
335
static const value_string wccp_address_family_val[] = {
336
  { 0, "Reserved" },
337
  { 1, "IPv4" },
338
  { 2, "IPv6" },
339
  { 0, NULL }
340
};
341
342
343
1
#define WCCP2_HASH_ASSIGNMENT_TYPE         0
344
0
#define WCCP2_MASK_ASSIGNMENT_TYPE         1
345
2
#define WCCP2r1_ALT_MASK_ASSIGNMENT_TYPE   2
346
0
#define WCCP2r1_ASSIGNMENT_WEIGHT_STATUS   3
347
348
static const value_string assignment_type_vals[] = {
349
  { WCCP2_HASH_ASSIGNMENT_TYPE, "Hash" },
350
  { WCCP2_MASK_ASSIGNMENT_TYPE, "Mask" },
351
  { WCCP2r1_ALT_MASK_ASSIGNMENT_TYPE, "WCCP2r1 Alternate Mask"},
352
  { WCCP2r1_ASSIGNMENT_WEIGHT_STATUS, "WCCP2r1 Assignment Weight Status"},
353
  { 0,                          NULL }
354
};
355
356
17
#define HASH_INFO_SIZE          (4*(1+8+1))
357
358
39
#define WCCP2_SECURITY_INFO             0
359
0
#define WCCP2_SERVICE_INFO              1
360
1
#define WCCP2_ROUTER_ID_INFO            2
361
0
#define WCCP2_WC_ID_INFO                3
362
1
#define WCCP2_RTR_VIEW_INFO             4
363
7
#define WCCP2_WC_VIEW_INFO              5
364
0
#define WCCP2_REDIRECT_ASSIGNMENT       6
365
0
#define WCCP2_QUERY_INFO                7
366
3
#define WCCP2_CAPABILITIES_INFO         8
367
3
#define WCCP2_ALT_ASSIGNMENT            13
368
0
#define WCCP2_ASSIGN_MAP                14
369
0
#define WCCP2_COMMAND_EXTENSION         15
370
/* WCCP 2 r1 additions: */
371
1
#define WCCP2r1_ALT_ASSIGNMENT_MAP      16
372
23
#define WCCP2r1_ADDRESS_TABLE           17
373
374
  static const value_string info_type_vals[] = {
375
    { WCCP2_SECURITY_INFO,       "Security Info" },
376
    { WCCP2_SERVICE_INFO,        "Service Info" },
377
    { WCCP2_ROUTER_ID_INFO,      "Router Identity Info" },
378
    { WCCP2_WC_ID_INFO,          "Web-Cache Identity Info" },
379
    { WCCP2_RTR_VIEW_INFO,       "Router View Info" },
380
    { WCCP2_WC_VIEW_INFO,        "Web-Cache View Info" },
381
    { WCCP2_REDIRECT_ASSIGNMENT, "Assignment Info" },
382
    { WCCP2_QUERY_INFO,          "Router Query Info" },
383
    { WCCP2_CAPABILITIES_INFO,   "Capabilities Info" },
384
    { WCCP2_ALT_ASSIGNMENT,      "Alternate Assignment" },
385
    { WCCP2_ASSIGN_MAP,          "Assignment Map" },
386
    { WCCP2_COMMAND_EXTENSION,   "Command Extension" },
387
    { WCCP2r1_ALT_ASSIGNMENT_MAP, "Alternative Assignment Map" },
388
    { WCCP2r1_ADDRESS_TABLE,      "Address Table" },
389
    { 0,                         NULL }
390
  };
391
392
const value_string service_id_vals[] = {
393
  { 0x00, "HTTP" },
394
  { 0,    NULL }
395
};
396
397
typedef struct capability_flag {
398
  uint32_t value;
399
  const char *short_name;
400
  int* phf;
401
} capability_flag;
402
403
404
405
406
12
#define WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_HASH        0
407
2
#define WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_MASK        1
408
2
#define WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_NOT_PRESENT 2
409
11
#define WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_EXTENDED    3
410
411
static const value_string wccp_web_cache_assignment_data_type_val[] = {
412
  { WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_HASH        , "Hash Assignment Data Element"},
413
  { WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_MASK        , "Mask Assignment Data Element"},
414
  { WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_NOT_PRESENT , "Assignment Data Element Not Present"},
415
  { WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_EXTENDED    , "Extended Assignment Data Element"},
416
  { 0,                          NULL }
417
};
418
419
0
#define WCCP2_FORWARDING_METHOD         0x01
420
0
#define WCCP2_ASSIGNMENT_METHOD         0x02
421
0
#define WCCP2_PACKET_RETURN_METHOD      0x03
422
0
#define WCCP2_TRANSMIT_T                0x04
423
0
#define WCCP2_TIMER_SCALE               0x05
424
425
static const value_string capability_type_vals[] = {
426
  { WCCP2_FORWARDING_METHOD,    "Forwarding Method" },
427
  { WCCP2_ASSIGNMENT_METHOD,    "Assignment Method" },
428
  { WCCP2_PACKET_RETURN_METHOD, "Packet Return Method" },
429
  { WCCP2_TRANSMIT_T,           "Transmit_t Message interval values"},
430
  { WCCP2_TIMER_SCALE,          "Timer_scale Timeout scale values"},
431
  { 0, NULL }
432
};
433
434
435
/* with version 2.01 we now have a address table which is possibly present */
436
437
typedef struct wccp_address_table {
438
  bool in_use;
439
  int16_t family;
440
  int16_t version;
441
  uint16_t table_length;
442
  ws_in4_addr *table_ipv4;
443
  ws_in6_addr *table_ipv6;
444
} wccp_address_table;
445
446
static int wccp_bucket_info(uint8_t bucket_info, proto_tree *bucket_tree,
447
                            uint32_t start, tvbuff_t *tvb, int offset);
448
449
/* The V2 dissectors will return the remaining length of the packet
450
   and a negative number if there are missing bytes to finish the
451
   dissection */
452
static int dissect_wccp2_mask_assignment_data_element(tvbuff_t *tvb, int offset, int length, packet_info *pinfo,
453
                                                       proto_tree *info_tree, wccp_address_table* addr_table);
454
static int dissect_wccp2_hash_buckets_assignment_element(tvbuff_t *tvb, int offset, int length,
455
                                                          packet_info *pinfo, proto_tree *info_tree, wccp_address_table* addr_table);
456
static int   dissect_wccp2r1_address_table_info(tvbuff_t *tvb, int offset,
457
                                                int length, packet_info *pinfo, proto_tree *info_tree,
458
                                                wccp_address_table* wccp_wccp_address_table);
459
static int dissect_wccp2_hash_assignment_data_element(tvbuff_t *tvb, int offset, int length, packet_info *pinfo,
460
                                                       proto_tree *info_tree);
461
static int dissect_wccp2_assignment_weight_and_status_element(tvbuff_t *tvb, int offset, int length, packet_info *pinfo,
462
                                                               proto_tree *info_tree);
463
static int dissect_wccp2_extended_assignment_data_element(tvbuff_t *tvb, int offset, int length, packet_info *pinfo,
464
                                                           proto_tree *info_tree, wccp_address_table* addr_table);
465
static int dissect_wccp2_capability_element(tvbuff_t *tvb, int offset, int length,
466
                                             packet_info *pinfo _U_, proto_tree *info_tree);
467
static int   dissect_wccp2_mask_value_set_list(tvbuff_t *tvb, int offset,
468
                                               int length, packet_info *pinfo, proto_tree *info_tree, wccp_address_table* addr_table);
469
470
/* Utility functions */
471
static int dissect_wccp2_mask_value_set_element(tvbuff_t *tvb, int offset,
472
                                                 int length, int idx, packet_info *pinfo, proto_tree *info_tree, wccp_address_table* addr_table);
473
static int dissect_wccp2_alternate_mask_value_set_list(tvbuff_t *tvb, int offset,
474
                                                        int length, packet_info *pinfo _U_, proto_tree *info_tree, wccp_address_table* addr_table);
475
static int dissect_wccp2_alternate_mask_value_set_element(tvbuff_t *tvb, int offset, int length, unsigned el_index, packet_info *pinfo,
476
                                                    proto_tree *info_tree, wccp_address_table* addr_table);
477
static int dissect_wccp2_web_cache_value_element(tvbuff_t *tvb, int offset,
478
                                                  int length,  packet_info *pinfo, proto_tree *info_tree, wccp_address_table* addr_table);
479
static void dissect_32_bit_capability_flags(tvbuff_t *tvb, int curr_offset,
480
                                            uint16_t capability_val_len, int ett, const capability_flag *flags,
481
                                            proto_tree *element_tree, proto_item *header,
482
                                            proto_item *length_item, packet_info *pinfo);
483
static void dissect_transmit_t_capability(tvbuff_t *tvb, proto_item *te, int curr_offset,
484
                                          uint16_t capability_val_len, int ett, proto_tree *element_tree,
485
                                          proto_item *length_item, packet_info *pinfo);
486
static void dissect_timer_scale_capability(tvbuff_t *tvb, int curr_offset,
487
                                           uint16_t capability_val_len, int ett, proto_tree *element_tree,
488
                                           proto_item *length_item, packet_info *pinfo);
489
490
491
492
493
/*
494
 * In WCCP 2.01 addresses are encoded to support IPv6 with 32 bit fields
495
 *
496
 * handle the decoding
497
 */
498
499
static void
500
find_wccp_address_table(tvbuff_t *tvb, int offset,
501
                        packet_info *pinfo, proto_tree *wccp_tree _U_, wccp_address_table* wccp_wccp_address_table)
502
12
{
503
12
  uint16_t type;
504
12
  uint16_t item_length;
505
506
26
  for (;;) {
507
26
    if (4 > tvb_reported_length_remaining(tvb, offset)) {
508
      /* We've run out of packet data without finding an address table,
509
         so there's no address table in the packet. */
510
0
      return;
511
0
    }
512
26
    type = tvb_get_ntohs(tvb, offset);
513
26
    item_length = tvb_get_ntohs(tvb, offset+2);
514
515
26
    if ((item_length + 4U) > tvb_reported_length_remaining(tvb, offset)) {
516
      /* We've run out of packet data without finding an address table,
517
         so there's no address table in the packet. */
518
7
      return;
519
7
    }
520
521
19
    if (type == WCCP2r1_ADDRESS_TABLE)
522
5
      {
523
5
        dissect_wccp2r1_address_table_info(tvb, offset+4, item_length, pinfo, NULL, wccp_wccp_address_table);
524
        /* no need to decode the rest */
525
5
        return;
526
5
      }
527
528
14
    offset = offset + (item_length + 4);
529
14
  }
530
12
}
531
532
533
/* This function prints the IP or the encoded IP if the table exists */
534
535
/* at most an IPv6 IP: see
536
   http://stackoverflow.com/questions/166132/maximum-length-of-the-textual-representation-of-an-ipv6-address
537
538
   39 = 8 groups of 4 digits with 7 : characters
539
540
   or
541
542
   45 = IPv4 tunnel features: 0000:0000:0000:0000:0000:0000:192.168.0.1
543
*/
544
545
/* problem here is that the IP is in network byte order for IPv4
546
   we need to fix that
547
*/
548
549
static const char * decode_wccp_encoded_address(tvbuff_t *tvb, int offset, packet_info *pinfo,
550
                        proto_tree *info_tree _U_, wccp_address_table* addr_table)
551
228
{
552
228
  uint32_t host_addr;
553
228
  char *buffer;
554
555
  /* are we using an address table? */
556
228
  if (!addr_table->in_use)
557
228
    {
558
      /* no; return the IPv4 IP */
559
228
      host_addr = tvb_get_ipv4(tvb,offset);
560
228
      buffer = (char *) wmem_alloc(pinfo->pool, WS_INET_ADDRSTRLEN);
561
228
      ip_addr_to_str_buf(&host_addr, buffer, WS_INET_ADDRSTRLEN);
562
228
    }
563
0
  else
564
0
    {
565
      /* yes; we need to decode the encoded address */
566
0
      uint16_t reserv;
567
0
      uint16_t addr_index;
568
569
0
      host_addr = tvb_get_ntohl(tvb,offset);
570
0
      reserv = (host_addr & 0xFFFF0000) >> 16;
571
0
      addr_index = (host_addr & 0x0000FFFF);
572
573
0
      if (reserv != 0) {
574
0
        buffer = wmem_strdup(pinfo->pool, "INVALID: reserved part non zero");
575
0
      }
576
0
      else {
577
        /* now check if it's IPv4 or IPv6 we need to print */
578
0
        switch (addr_table->family) {
579
0
        case 1:
580
          /* IPv4 */
581
582
          /* special case: index 0 -> undefined IP */
583
0
          if (addr_index == 0) {
584
0
            buffer = wmem_strdup(pinfo->pool, "0.0.0.0");
585
0
            break;
586
0
          }
587
          /* are we be beyond the end of the table? */
588
0
          if (addr_index > addr_table->table_length) {
589
0
            buffer = wmem_strdup_printf(pinfo->pool, "INVALID IPv4 index: %d > %d",
590
0
                       addr_index, addr_table->table_length);
591
0
            break;
592
0
          }
593
594
          /* ok get the IP */
595
0
          if (addr_table->table_ipv4 != NULL) {
596
0
            buffer = (char *) wmem_alloc(pinfo->pool, WS_INET_ADDRSTRLEN);
597
0
            ip_addr_to_str_buf(&addr_table->table_ipv4[addr_index-1], buffer, WS_INET_ADDRSTRLEN);
598
0
          }
599
0
          else {
600
0
            buffer = wmem_strdup(pinfo->pool, "INVALID IPv4 table empty!");
601
0
          }
602
0
          break;
603
0
        case 2:
604
          /* IPv6 */
605
          /* special case: index 0 -> undefined IP */
606
0
          if (addr_index == 0) {
607
0
            buffer = wmem_strdup(pinfo->pool, "::");
608
0
            break;
609
0
          }
610
611
          /* are we be beyond the end of the table? */
612
0
          if (addr_index > addr_table->table_length) {
613
0
            buffer = wmem_strdup_printf(pinfo->pool, "INVALID IPv6 index: %d > %d",
614
0
                       addr_index, addr_table->table_length);
615
0
            break;
616
0
          }
617
618
          /* ok get the IP */
619
0
          if (addr_table->table_ipv6 != NULL) {
620
0
            buffer = (char *) wmem_alloc(pinfo->pool, WS_INET6_ADDRSTRLEN);
621
0
            ip6_to_str_buf(&(addr_table->table_ipv6[addr_index-1]), buffer, WS_INET6_ADDRSTRLEN);
622
0
          }
623
0
          else {
624
0
            buffer = wmem_strdup(pinfo->pool, "INVALID IPv6 table empty!");
625
0
          }
626
0
          break;
627
0
        default:
628
0
          buffer = wmem_strdup(pinfo->pool, "INVALID IP family");
629
0
          break;
630
0
        }
631
0
      }
632
0
    }
633
634
228
  return buffer;
635
228
}
636
637
static proto_item* wccp_add_ipaddress_item(proto_tree* tree, int hf_index, int hf_ipv4, int hf_ipv6, tvbuff_t *tvb,
638
                                    int offset, int length, wccp_address_table* addr_table)
639
751
{
640
751
    uint32_t host_addr;
641
751
    ws_in6_addr ipv6_zero;
642
751
    uint16_t reserv, addr_index;
643
644
    /* are we using an address table? */
645
751
    if (! addr_table->in_use)
646
320
      return proto_tree_add_item(tree, hf_ipv4, tvb, offset, length, ENC_BIG_ENDIAN);
647
648
431
    host_addr = tvb_get_ntohl(tvb, offset);
649
650
    /* we need to decode the encoded address: */
651
431
    reserv = (host_addr & 0xFFFF0000) >> 16;
652
431
    addr_index  = (host_addr & 0x0000FFFF);
653
654
431
    memset(&ipv6_zero, 0, sizeof(ipv6_zero));
655
656
431
    if (reserv != 0)
657
350
      return proto_tree_add_uint_format_value(tree, hf_index, tvb, offset, length, host_addr, "INVALID: reserved part non zero");
658
659
    /* now check if it's IPv4 or IPv6 we need to print */
660
81
    switch (addr_table->family) {
661
0
    case 1:
662
    /* IPv4 */
663
664
        /* special case: index 0 -> undefined IP */
665
0
        if (addr_index == 0) {
666
0
          return proto_tree_add_item(tree, hf_ipv4, tvb, offset, length, ENC_LITTLE_ENDIAN);
667
0
        }
668
        /* are we be beyond the end of the table? */
669
0
        if (addr_index > addr_table->table_length) {
670
0
          return proto_tree_add_uint_format_value(tree, hf_index, tvb, offset, length, host_addr,
671
0
                     "INVALID IPv4 index: %d > %d", addr_index, addr_table->table_length);
672
0
        }
673
674
        /* ok get the IP */
675
0
        if (addr_table->table_ipv4 != NULL) {
676
0
          return proto_tree_add_ipv4(tree, hf_ipv4, tvb, offset, length, addr_table->table_ipv4[addr_index-1]);
677
0
        }
678
679
0
        return proto_tree_add_uint_format_value(tree, hf_index, tvb, offset, length, host_addr, "INVALID: IPv4 table empty!");
680
681
0
    case 2:
682
        /* IPv6 */
683
        /* special case: index 0 -> undefined IP */
684
0
        if (addr_index == 0) {
685
0
          return proto_tree_add_ipv6(tree, hf_ipv6, tvb, offset, length, &ipv6_zero);
686
0
        }
687
688
        /* are we be beyond the end of the table? */
689
0
        if (addr_index > addr_table->table_length) {
690
0
          return proto_tree_add_uint_format_value(tree, hf_index, tvb, offset, length, host_addr,
691
0
                        "INVALID IPv6 index: %d > %d", addr_index, addr_table->table_length);
692
0
        }
693
694
        /* ok get the IP */
695
0
        if (addr_table->table_ipv6 != NULL) {
696
0
          return proto_tree_add_ipv6(tree, hf_ipv6, tvb, offset, length, &(addr_table->table_ipv6[addr_index-1]));
697
0
        }
698
699
0
        return proto_tree_add_uint_format_value(tree, hf_index, tvb, offset, length, host_addr,
700
0
                        "INVALID IPv6 table empty!");
701
81
    }
702
703
79
    return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, host_addr, "INVALID IP family");
704
81
}
705
706
#define WCCP_IP_MAX_LENGTH (WS_INET_ADDRSTRLEN > 46 ? WS_INET_ADDRSTRLEN : 46)
707
708
709
static unsigned
710
dissect_hash_data(tvbuff_t *tvb, int offset, proto_tree *wccp_tree)
711
17
{
712
17
  proto_tree *bucket_tree;
713
17
  proto_item *tf;
714
17
  proto_tree *field_tree;
715
17
  int i;
716
17
  uint8_t bucket_info;
717
17
  int n;
718
719
17
  proto_tree_add_item(wccp_tree, hf_hash_revision, tvb, offset, 4,
720
17
                      ENC_BIG_ENDIAN);
721
17
  offset += 4;
722
723
17
  bucket_tree = proto_tree_add_subtree(wccp_tree, tvb, offset, 32,
724
17
                                    ett_buckets, NULL, "Hash information");
725
726
531
  for (i = 0, n = 0; i < 32; i++) {
727
514
    bucket_info = tvb_get_uint8(tvb, offset);
728
514
    n = wccp_bucket_info(bucket_info, bucket_tree, n, tvb, offset);
729
514
    offset += 1;
730
514
  }
731
17
  tf = proto_tree_add_item(wccp_tree, hf_hash_flag, tvb, offset, 4, ENC_BIG_ENDIAN);
732
17
  field_tree = proto_item_add_subtree(tf, ett_hash_flags);
733
17
  proto_tree_add_item(field_tree, hf_hash_flag_u, tvb, offset, 4, ENC_BIG_ENDIAN);
734
17
  offset += 4;
735
17
  return offset;
736
17
}
737
738
static unsigned
739
dissect_web_cache_list_entry(tvbuff_t *tvb, int offset, int idx,
740
                             proto_tree *wccp_tree)
741
17
{
742
17
  proto_tree *list_entry_tree;
743
744
17
  list_entry_tree = proto_tree_add_subtree_format(wccp_tree, tvb, offset, 4 + HASH_INFO_SIZE,
745
17
                           ett_cache_info, NULL, "Web-Cache List Entry(%d)", idx);
746
17
  proto_tree_add_item(list_entry_tree, hf_cache_ip, tvb, offset, 4,
747
17
                      ENC_BIG_ENDIAN);
748
17
  offset += 4;
749
17
  offset = dissect_hash_data(tvb, offset, list_entry_tree);
750
17
  return offset;
751
17
}
752
753
/*
754
 * wccp_bucket_info()
755
 * takes an integer representing a "Hash Information" bitmap, and spits out
756
 * the corresponding proto_tree entries, returning the next bucket number.
757
 */
758
static int
759
wccp_bucket_info(uint8_t bucket_info, proto_tree *bucket_tree, uint32_t start,
760
                 tvbuff_t *tvb, int offset)
761
897
{
762
897
  uint32_t i;
763
764
8.07k
  for(i = 0; i < 8; i++) {
765
7.17k
    proto_tree_add_uint_format(bucket_tree, hf_bucket_bit, tvb, offset, 1, bucket_info & 1<<i,
766
7.17k
                    "Bucket %3d: %s", start, (bucket_info & 1<<i ? "Assigned" : "Not Assigned") );
767
7.17k
    start++;
768
7.17k
  }
769
897
  return start;
770
897
}
771
772
773
/* the following functions all need to check the length and the offset
774
   so we have a few macros to use
775
*/
776
777
1.67k
#define EAT(x) {length -= x; offset += x;}
778
779
158
#define EAT_AND_CHECK(x,next) {length -= x; offset += x; if (length < next) return length - next;}
780
781
66
#define CHECK_LENGTH_ADVANCE_OFFSET(new_length) { \
782
66
  int old_offset = offset; \
783
66
  if (new_length<0) return new_length; \
784
66
  offset += length-new_length; \
785
63
  if (old_offset >= offset) return offset - old_offset; \
786
63
  length = new_length; \
787
62
  }
788
789
790
/* 5.1.1 Security Info Component */
791
792
/* Security options */
793
794
#define WCCP2_NO_SECURITY               0
795
3
#define WCCP2_MD5_SECURITY              1
796
797
75
#define SECURITY_INFO_LEN               4
798
799
static const value_string security_option_vals[] = {
800
  { WCCP2_NO_SECURITY, "None" },
801
  { WCCP2_MD5_SECURITY, "MD5" },
802
  { 0,    NULL }
803
};
804
805
806
static int
807
dissect_wccp2_security_info(tvbuff_t *tvb, int offset, int length,
808
                            packet_info *pinfo _U_, proto_tree *info_tree, wccp_address_table* addr_table _U_)
809
39
{
810
39
  uint32_t security_option;
811
812
39
  if (length < SECURITY_INFO_LEN)
813
36
    return (length-SECURITY_INFO_LEN);
814
815
3
  proto_tree_add_item_ret_uint(info_tree, hf_security_info_option, tvb, offset, 4, ENC_BIG_ENDIAN, &security_option);
816
817
3
  if (security_option == WCCP2_MD5_SECURITY) {
818
0
    offset += 4;
819
820
0
    proto_tree_add_item(info_tree, hf_security_info_md5_checksum, tvb, offset, length-4, ENC_NA);
821
822
0
    return length-4-16;
823
0
  }
824
3
  return length-4;
825
3
}
826
827
828
/* 5.1.2 Service Info Component */
829
830
0
#define SERVICE_INFO_LEN                (4+4+8*2)
831
832
0
#define WCCP2_SERVICE_STANDARD          0
833
0
#define WCCP2_SERVICE_DYNAMIC           1
834
835
static const value_string service_type_vals[] = {
836
  { WCCP2_SERVICE_STANDARD, "Standard predefined service"},
837
  { WCCP2_SERVICE_DYNAMIC, "Dynamic CE defined service" },
838
  { 0,    NULL }
839
};
840
841
/*
842
 * Service flags.
843
 */
844
16
#define WCCP2_SI_SRC_IP_HASH                    0x00000001
845
16
#define WCCP2_SI_DST_IP_HASH                    0x00000002
846
16
#define WCCP2_SI_SRC_PORT_HASH                  0x00000004
847
16
#define WCCP2_SI_DST_PORT_HASH                  0x00000008
848
16
#define WCCP2_SI_PORTS_DEFINED                  0x00000010
849
16
#define WCCP2_SI_PORTS_SOURCE                   0x00000020
850
16
#define WCCP2r1_SI_REDIRECT_ONLY_PROTOCOL_0     0x00000040
851
16
#define WCCP2_SI_SRC_IP_ALT_HASH                0x00000100
852
16
#define WCCP2_SI_DST_IP_ALT_HASH                0x00000200
853
16
#define WCCP2_SI_SRC_PORT_ALT_HASH              0x00000400
854
16
#define WCCP2_SI_DST_PORT_ALT_HASH              0x00000800
855
856
857
static int
858
dissect_wccp2_service_info(tvbuff_t *tvb, int offset, int length,
859
                           packet_info *pinfo, proto_tree *info_tree, wccp_address_table* addr_table _U_)
860
0
{
861
0
  uint8_t service_type;
862
0
  uint32_t flags;
863
0
  proto_item *tf;
864
0
  proto_tree *ports_tree;
865
0
  int i;
866
0
  int max_offset = offset+length;
867
868
0
  static int * const flag_fields[] = {
869
0
    &hf_service_info_flags_src_ip_hash,
870
0
    &hf_service_info_flags_dest_ip_hash,
871
0
    &hf_service_info_flags_src_port_hash,
872
0
    &hf_service_info_flags_dest_port_hash,
873
0
    &hf_service_info_flags_ports_defined,
874
0
    &hf_service_info_flags_ports_source,
875
0
    &hf_service_info_flags_redirect_only_protocol_0,
876
0
    &hf_service_info_flags_src_ip_alt_hash,
877
0
    &hf_service_info_flags_dest_ip_alt_hash,
878
0
    &hf_service_info_flags_src_port_alt_hash,
879
0
    &hf_service_info_flags_dest_port_alt_hash,
880
0
    &hf_service_info_flags_reserved,
881
0
    NULL
882
0
  };
883
884
0
  if (length != SERVICE_INFO_LEN)
885
0
    return length - SERVICE_INFO_LEN;
886
887
0
  service_type = tvb_get_uint8(tvb, offset);
888
0
  proto_tree_add_item(info_tree, hf_service_info_type, tvb,
889
0
                      offset, 1, ENC_BIG_ENDIAN);
890
891
0
  switch (service_type) {
892
893
0
  case WCCP2_SERVICE_STANDARD:
894
0
    proto_tree_add_item(info_tree, hf_service_info_id_standard, tvb,
895
0
                        offset +1 , 1, ENC_BIG_ENDIAN);
896
897
0
    tf = proto_tree_add_item(info_tree, hf_service_info_priority, tvb, offset+2, 1, ENC_BIG_ENDIAN);
898
0
    if (tvb_get_uint8(tvb, offset+2) != 0)
899
0
      expert_add_info(pinfo, tf, &ei_wccp_service_info_priority_nonzero);
900
901
0
    tf = proto_tree_add_item(info_tree, hf_service_info_protocol, tvb,
902
0
                        offset+3, 1, ENC_BIG_ENDIAN);
903
904
0
    if (tvb_get_uint8(tvb, offset+3) != 0)
905
0
      expert_add_info(pinfo, tf, &ei_wccp_service_info_protocol_nonzero);
906
0
    break;
907
908
0
  case WCCP2_SERVICE_DYNAMIC:
909
0
    proto_tree_add_item(info_tree, hf_service_info_id_dynamic, tvb,
910
0
                        offset +1 , 1, ENC_BIG_ENDIAN);
911
0
    proto_tree_add_item(info_tree, hf_service_info_priority, tvb,
912
0
                        offset+2, 1, ENC_BIG_ENDIAN);
913
0
    proto_tree_add_item(info_tree, hf_service_info_protocol, tvb,
914
0
                        offset+3, 1, ENC_BIG_ENDIAN);
915
0
    break;
916
0
  }
917
0
  offset += 4;
918
919
0
  flags = tvb_get_ntohl(tvb, offset);
920
0
  proto_tree_add_bitmask(info_tree, tvb, offset, hf_service_info_flags, ett_service_flags, flag_fields, ENC_BIG_ENDIAN);
921
922
0
  offset += 4;
923
924
0
  if (flags & WCCP2_SI_PORTS_DEFINED) {
925
0
    ports_tree = proto_tree_add_subtree(info_tree, tvb, offset, 2*8,
926
0
                             ett_service_info_ports, &tf, "Ports list: ");
927
928
0
    for (i = 0; i < 8; i++) {
929
0
      uint16_t port = tvb_get_ntohs(tvb, offset);
930
931
0
      if (port) {
932
0
        if (flags & WCCP2_SI_SRC_PORT_HASH)
933
0
          proto_tree_add_item(ports_tree, hf_service_info_source_port, tvb, offset, 2, ENC_BIG_ENDIAN);
934
0
        else
935
0
          proto_tree_add_item(ports_tree, hf_service_info_destination_port, tvb, offset, 2, ENC_BIG_ENDIAN);
936
0
        proto_item_append_text(tf, " %d", port);
937
0
      }
938
0
      offset += 2;
939
0
      DISSECTOR_ASSERT(offset <= max_offset);
940
0
    }
941
0
  }
942
0
  else {
943
    /* just use up the space if there is */
944
0
    if (offset + 8 * 2 <= max_offset)  {
945
0
      proto_tree_add_expert(info_tree, pinfo, &ei_wccp_port_fields_not_used, tvb, offset, 8*2);
946
      /*offset += 8*2;*/
947
0
    }
948
0
  }
949
950
0
  return length - SERVICE_INFO_LEN;
951
0
}
952
953
/* 6.1 Router Identity Element */
954
static void
955
dissect_wccp2_router_identity_element(tvbuff_t *tvb, int offset, packet_info *pinfo,
956
                                      proto_tree *tree, wccp_address_table* addr_table)
957
106
{
958
106
  proto_item *tf;
959
960
961
106
  wccp_add_ipaddress_item(tree, hf_router_identity_ip_index, hf_router_identity_ipv4, hf_router_identity_ipv6, tvb, offset, 4, addr_table);
962
106
  tf = proto_tree_add_item(tree, hf_router_identity_receive_id, tvb, offset+4, 4, ENC_BIG_ENDIAN);
963
964
106
  if (tvb_get_ntohl(tvb, offset + 4) == 0)
965
12
    expert_add_info(pinfo, tf, &ei_wccp_router_identity_receive_id_zero);
966
106
}
967
968
0
#define ROUTER_ID_INFO_MIN_LEN          (8+4+4)
969
970
/* 5.3.1 Router Identity Info Component */
971
static int
972
dissect_wccp2_router_identity_info(tvbuff_t *tvb, int offset, int length,
973
                                   packet_info *pinfo, proto_tree *info_tree, wccp_address_table* addr_table)
974
1
{
975
1
  uint32_t n_received_from;
976
1
  unsigned i;
977
1
  proto_item *te;
978
1
  proto_tree *element_tree;
979
980
1
  if (length < 8)
981
0
    return length -  ROUTER_ID_INFO_MIN_LEN;
982
983
984
1
  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);
985
986
1
  element_tree = proto_item_add_subtree(te,ett_wc_view_info_router_element);
987
988
1
  dissect_wccp2_router_identity_element(tvb,offset,pinfo,element_tree, addr_table);
989
1
  EAT_AND_CHECK(8,4);
990
991
1
  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);
992
1
  EAT_AND_CHECK(4,4);
993
994
1
  proto_tree_add_item_ret_uint(info_tree, hf_router_identity_received_from_num, tvb, offset, 4, ENC_BIG_ENDIAN, &n_received_from);
995
1
  EAT(4);
996
997
162
  for (i = 0; i < n_received_from; i++) {
998
161
    if (length < 4)
999
0
      return length-4*(i-n_received_from);
1000
1001
1002
161
    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);
1003
161
    EAT(4);
1004
161
  }
1005
1006
1
  return length;
1007
1
}
1008
1009
27
#define ROUTER_WC_ID_ELEMENT_MIN_LEN (4+2+2)
1010
1011
/* 6.4 Web-Cache Identity Element */
1012
static int
1013
dissect_wccp2_web_cache_identity_element(tvbuff_t *tvb, int offset, int length, packet_info *pinfo,
1014
                                         proto_tree *info_tree, wccp_address_table* addr_table)
1015
27
{
1016
27
  proto_item *tf;
1017
27
  uint16_t flags;
1018
27
  unsigned data_element_type;
1019
1020
27
  static int * const flag_fields[] = {
1021
27
    &hf_web_cache_identity_flag_hash_info,
1022
27
    &hf_web_cache_identity_flag_assign_type,
1023
27
    &hf_web_cache_identity_flag_version_request,
1024
27
    &hf_web_cache_identity_flag_reserved,
1025
27
    NULL
1026
27
  };
1027
1028
27
  if (length < ROUTER_WC_ID_ELEMENT_MIN_LEN)
1029
0
    return length - ROUTER_WC_ID_ELEMENT_MIN_LEN;
1030
1031
27
  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);
1032
27
  EAT_AND_CHECK(4,2);
1033
1034
27
  tf = proto_tree_add_item(info_tree, hf_web_cache_identity_hash_rev, tvb, offset, 2, ENC_BIG_ENDIAN);
1035
27
  if (tvb_get_ntohs(tvb, offset) != 0)
1036
23
    expert_add_info(pinfo, tf, &ei_wccp_web_cache_identity_hash_rev_zero);
1037
1038
27
  EAT_AND_CHECK(2,2);
1039
1040
27
  flags = tvb_get_ntohs(tvb, offset);
1041
27
  data_element_type = (flags & 0x6) >> 1;
1042
27
  proto_tree_add_bitmask(info_tree, tvb, offset, hf_web_cache_identity_flags, ett_wc_identity_flags, flag_fields, ENC_BIG_ENDIAN);
1043
1044
27
  EAT(2);
1045
1046
27
  switch (data_element_type) {
1047
12
  case WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_HASH:
1048
12
    return dissect_wccp2_hash_assignment_data_element(tvb,offset,length,pinfo,info_tree);
1049
2
  case WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_MASK:
1050
2
    return dissect_wccp2_mask_assignment_data_element(tvb,offset,length,pinfo,info_tree, addr_table);
1051
1052
2
  case WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_NOT_PRESENT:
1053
2
    proto_tree_add_item(info_tree, hf_assignment_no_data, tvb, offset, 2, ENC_NA);
1054
2
    return length;
1055
11
  case WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_EXTENDED:
1056
11
    return dissect_wccp2_extended_assignment_data_element(tvb,offset,length,pinfo,info_tree, addr_table);
1057
27
  }
1058
0
  return length;
1059
27
}
1060
1061
/* 5.2.1  Web-Cache Identity Info Component */
1062
static int
1063
dissect_wccp2_wc_identity_info(tvbuff_t *tvb, int offset, int length,
1064
                               packet_info *pinfo _U_, proto_tree *info_tree, wccp_address_table* addr_table)
1065
0
{
1066
0
  proto_item *te;
1067
0
  proto_tree *element_tree;
1068
1069
0
  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,
1070
0
                                tvb, offset, 4, addr_table);
1071
1072
0
  element_tree = proto_item_add_subtree(te, ett_wc_identity_element);
1073
0
  return dissect_wccp2_web_cache_identity_element(tvb, offset,length, pinfo,
1074
0
                                                  element_tree, addr_table);
1075
0
}
1076
1077
/* 6.3 Assignment Key Element */
1078
static int
1079
dissect_wccp2_assignment_key_element(tvbuff_t *tvb, int offset, int length, packet_info *pinfo _U_,
1080
                                     proto_tree *info_tree, wccp_address_table* addr_table)
1081
4
{
1082
4
  if (length < 8)
1083
0
    return length -8;
1084
1085
1086
4
  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
1088
4
  EAT_AND_CHECK(4,4);
1089
4
  proto_tree_add_item(info_tree, hf_assignment_key_change_num, tvb, offset, 4, ENC_BIG_ENDIAN);
1090
4
  EAT(4);
1091
1092
4
  return length;
1093
4
}
1094
1095
1096
1
#define ROUTER_VIEW_INFO_MIN_LEN        (4+8+4+4)
1097
1098
/* 5.3.2 Router View Info Component */
1099
static int
1100
dissect_wccp2_router_view_info(tvbuff_t *tvb, int offset, int length,
1101
                               packet_info *pinfo, proto_tree *info_tree, wccp_address_table* addr_table)
1102
1
{
1103
1
  uint32_t n_routers;
1104
1
  uint32_t n_web_caches;
1105
1
  unsigned i;
1106
1
  proto_item *te;
1107
1
  proto_tree *element_tree;
1108
1
  int new_length;
1109
1110
1
  if (length < ROUTER_VIEW_INFO_MIN_LEN)
1111
0
    return length - ROUTER_VIEW_INFO_MIN_LEN;
1112
1113
1
  proto_tree_add_item(info_tree, hf_router_view_member_change_num, tvb, offset, 4, ENC_BIG_ENDIAN);
1114
1
  EAT(4);
1115
1116
1
  new_length=dissect_wccp2_assignment_key_element(tvb, offset, length, pinfo, info_tree, addr_table);
1117
2
  CHECK_LENGTH_ADVANCE_OFFSET(new_length);
1118
1119
2
  n_routers = tvb_get_ntohl(tvb, offset);
1120
2
  proto_tree_add_uint(info_tree, hf_router_router_num, tvb, offset, 4, n_routers);
1121
2
  EAT(4);
1122
1123
2
  for (i = 0; i < n_routers; i++) {
1124
0
    if (length < 4)
1125
0
      return length - (n_routers-i)*4 - 4;
1126
1127
0
    wccp_add_ipaddress_item(info_tree, hf_router_view_ip_index, hf_router_view_ipv4, hf_router_view_ipv6, tvb, offset, 4, addr_table);
1128
0
    EAT(4);
1129
0
  }
1130
1131
1
  if (length < 4)
1132
0
    return length - 4;
1133
1134
1
  n_web_caches = tvb_get_ntohl(tvb, offset);
1135
1
  proto_tree_add_uint(info_tree, hf_wc_view_wc_num, tvb, offset, 4, n_web_caches);
1136
1
  EAT(4);
1137
1138
28
  for (i = 0; i < n_web_caches; i++) {
1139
27
    int old_length;
1140
27
    old_length = length;
1141
1142
27
    if (length < 4)
1143
0
      return length - 4*(n_web_caches-i);
1144
1145
27
    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
1147
27
    element_tree = proto_item_add_subtree(te, ett_wc_identity_element);
1148
27
    length = dissect_wccp2_web_cache_identity_element(tvb,
1149
27
                                                      offset, length, pinfo,
1150
27
                                                      element_tree, addr_table);
1151
27
    if (length < 0)
1152
0
      return length;
1153
1154
27
    offset += old_length - length;
1155
27
  }
1156
1
  return length;
1157
1
}
1158
1159
10
#define WC_VIEW_INFO_MIN_LEN            (4+4+4)
1160
1161
/* 5.2.2 Web Cache View Info Component */
1162
1163
static int
1164
dissect_wccp2_web_cache_view_info(tvbuff_t *tvb, int offset, int length,
1165
                                  packet_info *pinfo, proto_tree *info_tree, wccp_address_table* addr_table)
1166
7
{
1167
7
  uint32_t n_routers;
1168
7
  uint32_t n_web_caches;
1169
7
  unsigned i;
1170
7
  proto_item *te;
1171
7
  proto_tree *element_tree;
1172
1173
1174
7
  if (length < WC_VIEW_INFO_MIN_LEN)
1175
3
    return length - WC_VIEW_INFO_MIN_LEN;
1176
1177
1178
4
  proto_tree_add_item(info_tree, hf_wc_view_info_change_num, tvb, offset, 4, ENC_BIG_ENDIAN);
1179
4
  EAT_AND_CHECK(4,4);
1180
1181
4
  n_routers = tvb_get_ntohl(tvb, offset);
1182
4
  proto_tree_add_uint(info_tree, hf_wc_view_router_num, tvb, offset, 4, n_routers);
1183
4
  EAT(4);
1184
1185
34
  for (i = 0; i < n_routers; i++) {
1186
32
    if (length < 8)
1187
2
      return length -8 * (n_routers-i) - 4;
1188
1189
30
    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);
1190
    /* also include the receive id in the object */
1191
30
    proto_item_set_len(te, 8);
1192
1193
30
    element_tree = proto_item_add_subtree(te,ett_wc_view_info_router_element);
1194
30
    dissect_wccp2_router_identity_element(tvb, offset, pinfo, element_tree, addr_table);
1195
30
    EAT(8);
1196
30
  }
1197
1198
2
  if (length < 4)
1199
0
    return length - 4;
1200
1201
2
  n_web_caches = tvb_get_ntohl(tvb, offset);
1202
2
  proto_tree_add_uint(info_tree, hf_wc_view_wc_num, tvb, offset, 4, n_web_caches);
1203
2
  EAT(4);
1204
1205
373
  for (i = 0; i < n_web_caches; i++) {
1206
371
    if (length < 4)
1207
0
      return length - 4*(n_web_caches-i);
1208
1209
371
    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);
1210
371
    EAT(4);
1211
371
  }
1212
2
  return length;
1213
2
}
1214
1215
/* 6.2 Router Assignment Element */
1216
static void
1217
dissect_wccp2_router_assignment_element(tvbuff_t *tvb, int offset,
1218
                                        int length _U_, packet_info *pinfo, proto_tree *info_tree, wccp_address_table* addr_table)
1219
75
{
1220
75
  dissect_wccp2_router_identity_element(tvb,offset,pinfo,info_tree, addr_table);
1221
75
  EAT(8);
1222
75
  proto_tree_add_item(info_tree, hf_router_assignment_element_change_num, tvb, offset, 4, ENC_BIG_ENDIAN);
1223
75
  EAT(4);
1224
75
}
1225
1226
static const char *
1227
assignment_bucket_name(wmem_allocator_t* allocator, uint8_t bucket)
1228
0
{
1229
0
  const char *cur;
1230
1231
0
  if (bucket == 0xff) {
1232
0
    cur= wmem_strdup(allocator, "Unassigned");
1233
0
  } else {
1234
0
    cur=wmem_strdup_printf(allocator, "%u%s", bucket & 0x7F,
1235
0
                         (bucket & 0x80) ? " (Alt)" : "");
1236
0
  }
1237
0
  return cur;
1238
0
}
1239
1240
0
#define ASSIGNMENT_INFO_MIN_LEN         (8+4+4)
1241
1242
/* 5.4.1 Assignment Info Component  */
1243
static int
1244
dissect_wccp2_assignment_info(tvbuff_t *tvb, int offset, int length,
1245
                              packet_info *pinfo, proto_tree *info_tree, wccp_address_table* addr_table)
1246
0
{
1247
0
  uint32_t n_routers;
1248
0
  unsigned i;
1249
0
  proto_item *te;
1250
0
  proto_tree *element_tree;
1251
0
  int new_length;
1252
1253
0
  if (length < ASSIGNMENT_INFO_MIN_LEN)
1254
0
    return length - ASSIGNMENT_INFO_MIN_LEN;
1255
1256
1257
0
  new_length=dissect_wccp2_assignment_key_element(tvb, offset, length, pinfo, info_tree, addr_table);
1258
0
  CHECK_LENGTH_ADVANCE_OFFSET(new_length);
1259
1260
0
  n_routers = tvb_get_ntohl(tvb, offset);
1261
0
  proto_tree_add_uint(info_tree, hf_assignment_info_router_num, tvb, offset, 4, n_routers);
1262
0
  EAT(4);
1263
1264
0
  for (i = 0; i < n_routers; i++) {
1265
0
    if (length < 12)
1266
0
      return length - 12*(n_routers-i)-4-256;
1267
1268
0
    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
1270
0
    element_tree = proto_item_add_subtree(te, ett_router_assignment_element);
1271
0
    dissect_wccp2_router_assignment_element(tvb, offset, length , pinfo,
1272
0
                                            element_tree, addr_table);
1273
0
    EAT(12);
1274
0
  }
1275
1276
0
  new_length = dissect_wccp2_hash_buckets_assignment_element(tvb, offset, length, pinfo, info_tree, addr_table);
1277
0
  CHECK_LENGTH_ADVANCE_OFFSET(new_length);
1278
0
  return length;
1279
0
}
1280
1281
1282
0
#define QUERY_INFO_LEN                  (4+4+4+4)
1283
1284
/* 5.5.1 Router Query Info Component */
1285
static int
1286
dissect_wccp2_router_query_info(tvbuff_t *tvb, int offset, int length,
1287
                                packet_info *pinfo, proto_tree *info_tree, wccp_address_table* addr_table)
1288
0
{
1289
0
  if (length < QUERY_INFO_LEN)
1290
0
    return length - QUERY_INFO_LEN;
1291
1292
0
  dissect_wccp2_router_identity_element(tvb,offset,pinfo,info_tree, addr_table);
1293
0
  EAT_AND_CHECK(8,4);
1294
1295
0
  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);
1296
0
  EAT_AND_CHECK(4,4);
1297
0
  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);
1298
0
  EAT(4);
1299
1300
0
  return length;
1301
0
}
1302
1303
/* 6.5 Hash Buckets Assignment Element */
1304
static int dissect_wccp2_hash_buckets_assignment_element(tvbuff_t *tvb, int offset, int length,
1305
                                                          packet_info *pinfo _U_, proto_tree *info_tree, wccp_address_table* addr_table)
1306
0
{
1307
0
  uint32_t i,n_web_caches;
1308
0
  proto_item *te;
1309
0
  proto_tree *element_tree;
1310
0
  uint8_t bucket;
1311
1312
0
  if (length < 4)
1313
0
    return length - 4;
1314
1315
0
  te = proto_tree_add_item_ret_uint(info_tree, hf_hash_buckets_assignment_wc_num, tvb, offset, 4, ENC_BIG_ENDIAN, &n_web_caches);
1316
0
  EAT(4);
1317
1318
0
  element_tree = proto_item_add_subtree(te,ett_hash_buckets_assignment_wc_element);
1319
0
  for (i = 0; i < n_web_caches; i++) {
1320
0
    proto_item *l_te;
1321
1322
0
    if (length < 4)
1323
0
      return length - 4*(n_web_caches-i)-256;
1324
1325
0
    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
1327
0
    proto_item_append_text(l_te, " id: %d", i);
1328
0
    EAT(4);
1329
0
  }
1330
1331
0
  element_tree = proto_tree_add_subtree(info_tree,tvb, offset, 256, ett_hash_buckets_assignment_buckets, NULL, "Buckets");
1332
1333
0
  for (i = 0; i < 256; i++, offset++, length--) {
1334
0
    if (length < 1)
1335
0
      return length - (256-i);
1336
0
    bucket = tvb_get_uint8(tvb, offset);
1337
0
    proto_tree_add_uint_format(element_tree, hf_bucket, tvb, offset, 1,
1338
0
                        bucket, "Bucket %3d: %10s",
1339
0
                        i, assignment_bucket_name(pinfo->pool, bucket));
1340
0
  }
1341
0
  return length;
1342
0
}
1343
1344
16
#define WCCP2_FORWARDING_METHOD_GRE     0x00000001
1345
16
#define WCCP2_FORWARDING_METHOD_L2      0x00000002
1346
1347
static const capability_flag forwarding_method_flags[] = {
1348
  { WCCP2_FORWARDING_METHOD_GRE, "IP-GRE", &hf_capability_forwarding_method_flag_gre },
1349
  { WCCP2_FORWARDING_METHOD_L2, "L2", &hf_capability_forwarding_method_flag_l2 },
1350
  { 0, NULL, NULL }
1351
};
1352
1353
16
#define WCCP2_ASSIGNMENT_METHOD_HASH    0x00000001
1354
16
#define WCCP2_ASSIGNMENT_METHOD_MASK    0x00000002
1355
1356
static const capability_flag assignment_method_flags[] = {
1357
  { WCCP2_ASSIGNMENT_METHOD_HASH, "Hash", &hf_capability_assignment_method_flag_hash },
1358
  { WCCP2_ASSIGNMENT_METHOD_MASK, "Mask", &hf_capability_assignment_method_flag_mask },
1359
  { 0,                            NULL,   NULL }
1360
};
1361
1362
1363
16
#define WCCP2_PACKET_RETURN_METHOD_GRE  0x00000001
1364
16
#define WCCP2_PACKET_RETURN_METHOD_L2   0x00000002
1365
1366
static const capability_flag packet_return_method_flags[] = {
1367
  { WCCP2_PACKET_RETURN_METHOD_GRE, "IP-GRE", &hf_capability_return_method_flag_gre },
1368
  { WCCP2_PACKET_RETURN_METHOD_L2, "L2", &hf_capability_return_method_flag_l2 },
1369
  { 0, NULL, NULL }
1370
};
1371
1372
0
#define WCCP2_COMMAND_TYPE_SHUTDOWN           1
1373
0
#define WCCP2_COMMAND_TYPE_SHUTDOWN_RESPONSE  2
1374
1375
static const value_string wccp_command_type_vals[] = {
1376
  { WCCP2_COMMAND_TYPE_SHUTDOWN,          "CE shutting down" },
1377
  { WCCP2_COMMAND_TYPE_SHUTDOWN_RESPONSE, "Router Acknowledge CE shutdown"},
1378
  { 0, NULL }
1379
};
1380
1381
1382
1383
/* 5.1.3 Capabilities Info Component */
1384
1385
static int
1386
dissect_wccp2_capability_info(tvbuff_t *tvb, int offset, int length,
1387
                              packet_info *pinfo, proto_tree *info_tree, wccp_address_table* addr_table _U_)
1388
3
{
1389
3
  int capability_length;
1390
1391
39
  while (length >= 8) {
1392
36
    capability_length = dissect_wccp2_capability_element(tvb,offset,length,pinfo,info_tree);
1393
1394
72
    CHECK_LENGTH_ADVANCE_OFFSET(capability_length);
1395
72
  }
1396
3
  return length;
1397
3
}
1398
1399
1400
0
#define ALT_COMMAND_EXTENSION_MIN_LEN  (4)
1401
1402
/* 5.1.4 && 6.12 Command Extension Component */
1403
1404
static int
1405
dissect_wccp2_command_extension(tvbuff_t *tvb, int offset,
1406
                                int length, packet_info *pinfo _U_, proto_tree *info_tree, wccp_address_table* addr_table)
1407
0
{
1408
0
  uint16_t command_type;
1409
0
  uint32_t command_length;
1410
1411
0
  for (;;) {
1412
0
    if (length == 0)
1413
0
      return length;
1414
1415
0
    if (length < ALT_COMMAND_EXTENSION_MIN_LEN )
1416
0
      return length - ALT_COMMAND_EXTENSION_MIN_LEN ;
1417
1418
0
    proto_tree_add_item_ret_uint16(info_tree, hf_command_element_type, tvb, offset, 2, ENC_BIG_ENDIAN, &command_type);
1419
0
    EAT_AND_CHECK(2,2);
1420
1421
0
    proto_tree_add_item_ret_uint(info_tree, hf_command_element_length, tvb, offset, 2, ENC_BIG_ENDIAN, &command_length);
1422
0
    proto_tree_add_item(info_tree, hf_command_length, tvb, offset, 2, ENC_BIG_ENDIAN);
1423
0
    EAT(2);
1424
1425
0
    if (((command_type == WCCP2_COMMAND_TYPE_SHUTDOWN) ||
1426
0
         (command_type == WCCP2_COMMAND_TYPE_SHUTDOWN_RESPONSE)) &&
1427
0
        (command_length == 4)) {
1428
0
      if (length < 4)
1429
0
        return length - 4;
1430
1431
0
      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
0
    } else {
1433
0
      if (length < (int)command_length)
1434
0
        return length - command_length;
1435
1436
0
      proto_tree_add_item(info_tree, hf_command_unknown, tvb, offset, command_length, ENC_NA);
1437
0
    }
1438
0
    EAT(command_length);
1439
0
  }
1440
0
}
1441
1442
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
1446
*/
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)
1450
9
{
1451
9
  uint16_t address_length;
1452
9
  uint32_t i;
1453
9
  uint16_t family;
1454
9
  uint32_t table_length;
1455
9
  proto_tree *element_tree;
1456
9
  proto_item *tf;
1457
1458
9
  if (length < 2*4)
1459
2
    return length - 2*4;
1460
1461
7
  proto_tree_add_item_ret_uint16(info_tree, hf_address_table_family, tvb, offset, 2, ENC_BIG_ENDIAN, &family);
1462
7
  EAT_AND_CHECK(2,2);
1463
1464
7
  proto_tree_add_item_ret_uint16(info_tree, hf_address_table_address_length, tvb, offset, 2, ENC_BIG_ENDIAN, &address_length);
1465
7
  EAT_AND_CHECK(2,2);
1466
1467
7
  tf = proto_tree_add_item_ret_uint(info_tree, hf_address_table_length, tvb, offset, 4, ENC_BIG_ENDIAN, &table_length);
1468
7
  element_tree = proto_item_add_subtree(tf, ett_table_element);
1469
7
  EAT(4);
1470
1471
  /* Allocate the tables if needed */
1472
  /* An address table component is not allowed to appear more than once in
1473
   * a packet, so we take the first one. */
1474
7
  if (wccp_wccp_address_table->in_use == false) {
1475
4
    wccp_wccp_address_table->family = family;
1476
4
    wccp_wccp_address_table->table_length =  table_length;
1477
1478
4
    switch (wccp_wccp_address_table->family) {
1479
2
    case 1:
1480
2
      if (wccp_wccp_address_table->table_ipv4 == NULL)
1481
2
        wccp_wccp_address_table->table_ipv4 = (uint32_t *)
1482
2
          wmem_alloc0(pinfo->pool, wccp_wccp_address_table->table_length * 4);
1483
2
      break;
1484
0
    case 2:
1485
0
      if (wccp_wccp_address_table->table_ipv6 == NULL)
1486
0
        wccp_wccp_address_table->table_ipv6 = (ws_in6_addr *)
1487
0
          wmem_alloc0(pinfo->pool, wccp_wccp_address_table->table_length * sizeof(ws_in6_addr));
1488
0
      break;
1489
4
    };
1490
4
  }
1491
1492
  /* Check if the length is valid */
1493
7
  switch (family) {
1494
3
    case 1:
1495
3
      if (address_length != 4) {
1496
3
        expert_add_info_format(pinfo, tf, &ei_wccp_length_bad,
1497
3
                               "The Address length must be 4, but I found %d for IPv4 addresses. Correcting this.",
1498
3
                               address_length);
1499
3
        address_length = 4;
1500
3
      }
1501
3
      break;
1502
0
    case 2:
1503
0
      if (address_length != 16) {
1504
0
        expert_add_info_format(pinfo, tf, &ei_wccp_length_bad,
1505
0
                               "The Address length must be 16, but I found %d for IPv6 addresses. Correcting this.",
1506
0
                               address_length);
1507
0
        address_length = 16;
1508
0
      }
1509
0
      break;
1510
4
    default:
1511
4
      expert_add_info_format(pinfo, tf, &ei_wccp_address_table_family_unknown,
1512
4
                      "Unknown address family: %u", wccp_wccp_address_table->family);
1513
4
      if (address_length % 4) {
1514
0
        expert_add_info_format(pinfo, tf, &ei_wccp_length_bad,
1515
0
                               "The Address length must be a multiple of 4. Correcting this.");
1516
0
        address_length = WS_ROUNDUP_4(address_length);
1517
0
      }
1518
      /* XXX - In addition to an address length that starts out at 0, the
1519
       * WS_ROUNDUP_ family can "round up" numbers near UINT_MAX to 0. */
1520
4
      if (address_length == 0) {
1521
0
        expert_add_info_format(pinfo, tf, &ei_wccp_length_bad,
1522
0
                               "The Address length must be at least 4. Correcting this.");
1523
0
        address_length = 4;
1524
0
      }
1525
7
  }
1526
1527
  /* now read the addresses and print/store them */
1528
1529
206
  for(i=0; i<table_length; i++) {
1530
200
    const char *addr;
1531
1532
200
    switch (family) {
1533
200
    case 1:
1534
      /* IPv4 */
1535
200
      addr  =  tvb_ip_to_str(pinfo->pool, tvb, offset);
1536
200
      if ((wccp_wccp_address_table->in_use == false) &&
1537
199
          (wccp_wccp_address_table->table_ipv4 != NULL) &&
1538
199
          (i < wccp_wccp_address_table->table_length))
1539
65
        wccp_wccp_address_table->table_ipv4[i] = tvb_get_ipv4(tvb, offset);
1540
200
      break;
1541
0
    case 2:
1542
      /* IPv6 */
1543
0
      addr = tvb_ip6_to_str(pinfo->pool, tvb, offset);
1544
0
      if ((wccp_wccp_address_table->in_use == false) &&
1545
0
          (wccp_wccp_address_table->table_ipv6 != NULL) &&
1546
0
          (i < wccp_wccp_address_table->table_length))
1547
0
        tvb_get_ipv6(tvb, offset, &(wccp_wccp_address_table->table_ipv6[i]));
1548
0
      break;
1549
0
    default:
1550
0
      addr = wmem_strdup_printf(pinfo->pool, "unknown family %d", wccp_wccp_address_table->family);
1551
200
    };
1552
1553
199
    proto_item *pi;
1554
1555
199
    pi = proto_tree_add_string_format_value(element_tree, hf_address_table_element, tvb,
1556
199
                                            offset, address_length, addr,
1557
199
                                            "%d: %s", i+1, addr);
1558
199
    if (i > wccp_wccp_address_table->table_length)
1559
133
      expert_add_info_format(pinfo, pi, &ei_wccp_length_bad, "Ran out of space to store address");
1560
199
    EAT(address_length);
1561
199
  }
1562
1563
6
  wccp_wccp_address_table->in_use = true;
1564
6
  return length;
1565
7
}
1566
1567
1568
1569
1570
1571
1
#define HASH_ASSIGNMENT_INFO_MIN_LEN (4+256)
1572
1573
/* part of 5.6.11 Alternate Assignment Component */
1574
static int
1575
dissect_wccp2_hash_assignment_info(tvbuff_t *tvb, int offset, int length,
1576
                                   packet_info *pinfo, proto_tree *info_tree, wccp_address_table* addr_table)
1577
1
{
1578
1
  uint32_t n_web_caches, host_addr;
1579
1
  unsigned i;
1580
1
  uint8_t bucket;
1581
1582
1
  if (length < HASH_ASSIGNMENT_INFO_MIN_LEN)
1583
0
    return length - ASSIGNMENT_INFO_MIN_LEN;
1584
1585
1
  proto_tree_add_item_ret_uint(info_tree, hf_wc_view_wc_num, tvb, offset, 4, ENC_BIG_ENDIAN, &n_web_caches);
1586
1
  EAT(4);
1587
1588
146
  for (i = 0; i < n_web_caches; i++) {
1589
145
    if (length < 4)
1590
0
      return length - 4*(n_web_caches-i)-256;
1591
1592
145
    host_addr = tvb_get_ntohl(tvb,offset);
1593
145
    if (! addr_table->in_use){
1594
144
      proto_tree_add_ipv4_format(info_tree, hf_cache_ip, tvb, offset, 4, host_addr, "Web-Cache %d: IP address %s", i,
1595
144
                        decode_wccp_encoded_address(tvb, offset, pinfo, info_tree, addr_table));
1596
144
    } else {
1597
1
      proto_tree_add_uint_format(info_tree, hf_web_cache_identity_index, tvb, offset, 4, host_addr, "Web-Cache %d: IP address %s", i,
1598
1
                        decode_wccp_encoded_address(tvb, offset, pinfo, info_tree, addr_table));
1599
1
    }
1600
145
    EAT(4);
1601
145
  }
1602
1603
1604
1
  for (i = 0; i < 256; i++, offset++, length--) {
1605
0
    if (length < 1)
1606
0
      return length - (256-i);
1607
0
    bucket = tvb_get_uint8(tvb, offset);
1608
0
    proto_tree_add_uint_format(info_tree, hf_bucket, tvb, offset, 1,
1609
0
                        bucket, "Bucket %3d: %10s",
1610
0
                        i, assignment_bucket_name(pinfo->pool, bucket));
1611
0
  }
1612
1
  return length;
1613
1
}
1614
1615
/* 5.3.3 Assignment Map Component */
1616
static int dissect_wccp2_assignment_map(tvbuff_t *tvb, int offset,
1617
                                         int length, packet_info *pinfo, proto_tree *info_tree, wccp_address_table* addr_table)
1618
0
{
1619
0
  int new_length;
1620
1621
0
  new_length=dissect_wccp2_mask_value_set_list(tvb, offset, length, pinfo, info_tree, addr_table);
1622
1623
0
  CHECK_LENGTH_ADVANCE_OFFSET(new_length);
1624
1625
0
  return length;
1626
0
}
1627
1628
1629
1630
1
#define ALT_ASSIGNMENT_MAP_MIN_LEN  (4)
1631
1632
/* 5.3.4 Alternate Assignment Map Component */
1633
static int
1634
dissect_wccp2r1_alt_assignment_map_info(tvbuff_t *tvb, int offset,
1635
                                        int length, packet_info *pinfo, proto_tree *info_tree, wccp_address_table* addr_table)
1636
1
{
1637
1
  uint16_t assignment_type;
1638
1
  uint16_t assignment_length;
1639
1
  proto_item *tf=NULL;
1640
1641
1
  if (length < ALT_ASSIGNMENT_MAP_MIN_LEN )
1642
0
    return length - ALT_ASSIGNMENT_MAP_MIN_LEN ;
1643
1644
1
  proto_tree_add_item_ret_uint16(info_tree, hf_alt_assignment_map_assignment_type, tvb, offset, 2, ENC_BIG_ENDIAN, &assignment_type);
1645
1
  EAT_AND_CHECK(2,2);
1646
1647
1
  tf=proto_tree_add_item_ret_uint16(info_tree, hf_alt_assignment_map_assignment_length, tvb, offset, 2, ENC_BIG_ENDIAN, &assignment_length);
1648
1
  EAT(2);
1649
1650
1
  if (length < assignment_length)
1651
1
    expert_add_info_format(pinfo, tf, &ei_wccp_assignment_length_bad,
1652
1
                           "Assignment length is %d but only %d remain in the packet. Ignoring this for now",
1653
1
                           assignment_length, length);
1654
1655
1
  if (length > assignment_length)  {
1656
0
    expert_add_info_format(pinfo, tf, &ei_wccp_assignment_length_bad,
1657
0
                           "Assignment length is %d but %d remain in the packet. Assuming that the assignment length is wrong and setting it to %d.",
1658
0
                           assignment_length, length, length);
1659
0
    assignment_length = length;
1660
0
  }
1661
1662
1
  switch (assignment_type) {
1663
0
  case WCCP2_HASH_ASSIGNMENT_TYPE:
1664
0
    return dissect_wccp2_assignment_info(tvb, offset, assignment_length,
1665
0
                                         pinfo, info_tree, addr_table);
1666
0
  case WCCP2_MASK_ASSIGNMENT_TYPE:
1667
0
    return dissect_wccp2_mask_value_set_list(tvb, offset, assignment_length,
1668
0
                                             pinfo, info_tree, addr_table);
1669
1
  case WCCP2r1_ALT_MASK_ASSIGNMENT_TYPE:
1670
1
    return dissect_wccp2_alternate_mask_value_set_list(tvb, offset, assignment_length,
1671
1
                                                       pinfo, info_tree, addr_table);
1672
0
  default:
1673
0
    return length;
1674
1
  }
1675
1
}
1676
1677
1678
1679
1680
1681
/* 6.6 Hash Assignment Data Element */
1682
static int
1683
dissect_wccp2_hash_assignment_data_element(tvbuff_t *tvb, int offset, int length,
1684
                                           packet_info *pinfo _U_,
1685
                                           proto_tree *info_tree)
1686
1687
12
{
1688
12
  proto_tree *bucket_tree;
1689
12
  int i;
1690
12
  uint8_t bucket_info;
1691
12
  int n;
1692
1693
1694
12
  bucket_tree = proto_tree_add_subtree(info_tree, tvb, offset, 8*4,
1695
12
                                    ett_hash_assignment_buckets, NULL, "Hash Assignment Data");
1696
1697
396
  for (i = 0, n = 0; i < 32; i++) {
1698
384
    if (length == 0) {
1699
0
      return -i-2-2;
1700
0
    }
1701
1702
384
    bucket_info = tvb_get_uint8(tvb, offset);
1703
384
    n = wccp_bucket_info(bucket_info, bucket_tree, n, tvb, offset);
1704
384
    EAT(1);
1705
384
  }
1706
1707
12
  if (length < 2){
1708
0
    return -2-2;
1709
0
  }
1710
1711
12
  return dissect_wccp2_assignment_weight_and_status_element(tvb, offset, length, pinfo, info_tree);
1712
12
}
1713
1714
/* 6.7 Mask Assignment Data Element */
1715
static int
1716
dissect_wccp2_mask_assignment_data_element(tvbuff_t *tvb, int offset, int length, packet_info *pinfo,
1717
                                           proto_tree *info_tree, wccp_address_table* addr_table)
1718
1719
2
{
1720
2
  proto_item *mask_item;
1721
2
  proto_tree *mask_tree;
1722
2
  int new_length,start;
1723
1724
1725
2
  mask_tree = proto_tree_add_subtree(info_tree, tvb, offset, 4,
1726
2
                                  ett_mask_assignment_data_element, &mask_item, "Mask Assignment Data");
1727
2
  start = offset;
1728
1729
2
  new_length=dissect_wccp2_mask_value_set_list(tvb, offset, length, pinfo, mask_tree, addr_table);
1730
1731
4
  CHECK_LENGTH_ADVANCE_OFFSET(new_length);
1732
1733
4
  if (length < 2)
1734
0
    return length-4;
1735
1736
2
  new_length =  dissect_wccp2_assignment_weight_and_status_element(tvb, offset, length, pinfo, info_tree);
1737
2
  CHECK_LENGTH_ADVANCE_OFFSET(new_length);
1738
1739
2
  proto_item_set_len(mask_item, offset-start);
1740
2
  return length;
1741
2
}
1742
1743
1744
/* 5.7.5 Alternate Mask Assignment Data Element */
1745
static int
1746
dissect_wccp2_alternate_mask_assignment_data_element(tvbuff_t *tvb, int offset, int length, packet_info *pinfo,
1747
                                                     proto_tree *info_tree, wccp_address_table* addr_table)
1748
0
{
1749
0
  proto_tree *mask_tree;
1750
1751
0
  mask_tree = proto_tree_add_subtree(info_tree, tvb, offset, length,
1752
0
                                  ett_alternate_mask_assignment_data_element, NULL, "Alternate Mask Assignment Data");
1753
1754
0
  if (length < 4)
1755
0
    return length-4;
1756
1757
0
  if (length > 4)
1758
0
    for (;length >4;)
1759
0
      {
1760
0
        int new_length;
1761
1762
0
        new_length=dissect_wccp2_alternate_mask_value_set_list(tvb, offset, length, pinfo, mask_tree, addr_table);
1763
1764
0
        CHECK_LENGTH_ADVANCE_OFFSET(new_length);
1765
0
      }
1766
1767
0
  if (length < 2)
1768
0
    return -2;
1769
1770
0
  return  dissect_wccp2_assignment_weight_and_status_element(tvb, offset, length, pinfo, info_tree);
1771
0
}
1772
1773
1774
/* 6.9 Assignment Weight and Status Data Element */
1775
static int
1776
dissect_wccp2_assignment_weight_and_status_element(tvbuff_t *tvb, int offset, int length,
1777
                                                   packet_info *pinfo _U_,
1778
                                                   proto_tree *info_tree)
1779
1780
13
{
1781
13
  if (length < 4)
1782
0
    return length - 4;
1783
1784
1785
13
  proto_tree_add_item(info_tree, hf_assignment_weight, tvb, offset, 2, ENC_BIG_ENDIAN);
1786
13
  EAT_AND_CHECK(2,2);
1787
13
  proto_tree_add_item(info_tree, hf_assignment_status, tvb, offset, 2, ENC_BIG_ENDIAN);
1788
13
  EAT(2);
1789
13
  return length;
1790
13
}
1791
1792
1793
/* 6.10 Extended Assignment Data Element */
1794
static int
1795
dissect_wccp2_extended_assignment_data_element(tvbuff_t *tvb, int offset, int length, packet_info *pinfo,
1796
                                               proto_tree *info_tree, wccp_address_table* addr_table)
1797
11
{
1798
11
  proto_item *element_item, *header;
1799
11
  proto_tree *item_tree;
1800
1801
11
  unsigned type_of_assignment;
1802
1803
11
  int assignment_length;
1804
1805
11
  if (length < 4)
1806
0
    return length-4;
1807
1808
1809
11
  item_tree = proto_tree_add_subtree(info_tree, tvb, offset, length,
1810
11
                               ett_extended_assigment_data_element, &header, "Extended Assignment Data Element");
1811
1812
11
  type_of_assignment = tvb_get_ntohs(tvb, offset);
1813
11
  proto_tree_add_item(item_tree, hf_extended_assignment_data_type, tvb, offset, 2, ENC_BIG_ENDIAN);
1814
11
  EAT_AND_CHECK(2,2);
1815
1816
11
  assignment_length = tvb_get_ntohs(tvb,offset);
1817
11
  element_item = proto_tree_add_item(item_tree, hf_extended_assignment_data_length, tvb, offset, 2, ENC_BIG_ENDIAN);
1818
11
  EAT(2);
1819
1820
11
  if (length < assignment_length)
1821
10
    expert_add_info_format(pinfo, element_item, &ei_wccp_assignment_length_bad,
1822
10
                           "Assignment length is %d but only %d remain in the packet. Ignoring this for now",
1823
10
                           assignment_length, length);
1824
1825
  /* Now a common bug seems to be to set the assignment_length to the length -4
1826
     check for this */
1827
11
  if ((length > assignment_length) &&
1828
1
      (length == (assignment_length + 4)))
1829
0
    {
1830
0
      expert_add_info_format(pinfo, element_item, &ei_wccp_assignment_length_bad,
1831
0
                             "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",
1832
0
                             assignment_length, length, length);
1833
0
      assignment_length = length;
1834
0
    }
1835
1836
1837
11
  proto_item_set_len(header, assignment_length+4);
1838
1839
11
  switch (type_of_assignment)
1840
11
    {
1841
0
    case WCCP2_HASH_ASSIGNMENT_TYPE:
1842
0
      dissect_wccp2_hash_assignment_data_element(tvb, offset, assignment_length,
1843
0
                                                        pinfo, item_tree);
1844
0
      return length - assignment_length;
1845
0
    case WCCP2_MASK_ASSIGNMENT_TYPE:
1846
0
      dissect_wccp2_mask_assignment_data_element(tvb, offset, assignment_length,
1847
0
                                                        pinfo, item_tree, addr_table);
1848
0
      return length - assignment_length;
1849
0
    case WCCP2r1_ALT_MASK_ASSIGNMENT_TYPE:
1850
0
      dissect_wccp2_alternate_mask_assignment_data_element(tvb, offset, assignment_length,
1851
0
                                                                  pinfo, item_tree, addr_table);
1852
0
      return length - assignment_length;
1853
0
    case WCCP2r1_ASSIGNMENT_WEIGHT_STATUS:
1854
0
      dissect_wccp2_assignment_weight_and_status_element(tvb, offset, assignment_length,
1855
0
                                                                pinfo, item_tree);
1856
0
      return length - assignment_length;
1857
11
    }
1858
11
  return length;
1859
11
}
1860
1861
1862
1863
1864
1865
1866
/* 6.11 Capability Element */
1867
static int
1868
dissect_wccp2_capability_element(tvbuff_t *tvb, int offset, int length,
1869
                                 packet_info *pinfo, proto_tree *info_tree)
1870
36
{
1871
36
  uint16_t capability_type;
1872
36
  uint16_t capability_val_len;
1873
36
  proto_item *te, *header, *tf;
1874
36
  proto_tree *element_tree;
1875
1876
36
  if (length < 4)
1877
0
    return length - 4;
1878
1879
36
  capability_type = tvb_get_ntohs(tvb, offset);
1880
36
  element_tree = proto_tree_add_subtree_format(info_tree, tvb, offset, -1, ett_capability_element, &te,
1881
36
                                               "Type: %s",
1882
36
                                               val_to_str(pinfo->pool, capability_type,
1883
36
                                                          capability_type_vals,
1884
36
                                                          "Unknown (0x%08X)"));
1885
36
  header = te;
1886
1887
36
  proto_tree_add_item(element_tree, hf_capability_element_type, tvb, offset, 2, ENC_BIG_ENDIAN);
1888
1889
36
  capability_val_len = tvb_get_ntohs(tvb, offset+2);
1890
36
  tf = proto_tree_add_uint(element_tree, hf_capability_element_length, tvb, offset+2, 2, capability_val_len);
1891
36
  proto_item_set_len(te, capability_val_len + 4);
1892
1893
36
  if (length < (4+capability_val_len))
1894
0
    return length - (4 + capability_val_len);
1895
1896
36
  switch (capability_type) {
1897
0
  case WCCP2_FORWARDING_METHOD:
1898
0
    dissect_32_bit_capability_flags(tvb, offset,
1899
0
                                    capability_val_len,
1900
0
                                    ett_capability_forwarding_method,
1901
0
                                    forwarding_method_flags, element_tree,
1902
0
                                    header, tf, pinfo);
1903
0
    break;
1904
1905
0
  case WCCP2_ASSIGNMENT_METHOD:
1906
0
    dissect_32_bit_capability_flags(tvb, offset,
1907
0
                                    capability_val_len,
1908
0
                                    ett_capability_assignment_method,
1909
0
                                    assignment_method_flags, element_tree,
1910
0
                                    header, tf, pinfo);
1911
0
    break;
1912
1913
0
  case WCCP2_PACKET_RETURN_METHOD:
1914
0
    dissect_32_bit_capability_flags(tvb, offset,
1915
0
                                    capability_val_len,
1916
0
                                    ett_capability_return_method,
1917
0
                                    packet_return_method_flags, element_tree,
1918
0
                                    header, tf, pinfo);
1919
0
    break;
1920
1921
0
  case WCCP2_TRANSMIT_T:
1922
0
    dissect_transmit_t_capability(tvb, te, offset,
1923
0
                                  capability_val_len,
1924
0
                                  ett_capability_transmit_t, element_tree,
1925
0
                                  tf, pinfo);
1926
0
    break;
1927
1928
0
  case WCCP2_TIMER_SCALE:
1929
0
    dissect_timer_scale_capability(tvb, offset,
1930
0
                                   capability_val_len,
1931
0
                                   ett_capability_timer_scale, element_tree,
1932
0
                                   tf, pinfo);
1933
0
    break;
1934
36
  default:
1935
36
    proto_tree_add_item(element_tree, hf_capability_value, tvb, offset, capability_val_len, ENC_NA);
1936
36
    break;
1937
36
  }
1938
33
  return length - 4 - capability_val_len;
1939
36
}
1940
1941
1942
/* 6.13 Mask/Value Set List */
1943
static int
1944
dissect_wccp2_mask_value_set_list(tvbuff_t *tvb, int offset,
1945
                                  int length, packet_info *pinfo, proto_tree *info_tree, wccp_address_table* addr_table)
1946
2
{
1947
2
  unsigned num_of_elem;
1948
2
  unsigned i;
1949
2
  proto_item *te;
1950
2
  proto_tree *element_tree;
1951
2
  unsigned start;
1952
1953
1954
2
  if (length < 4)
1955
0
    return length - 4;
1956
1957
2
  element_tree = proto_tree_add_subtree(info_tree, tvb, offset, 4, ett_mv_set_list, &te, "Mask/Value Set List");
1958
2
  start = offset;
1959
1960
1961
2
  num_of_elem = tvb_get_ntohl(tvb, offset);
1962
2
  proto_tree_add_item(element_tree, hf_mask_value_set_list_num_elements,
1963
2
                      tvb, offset, 4, ENC_BIG_ENDIAN);
1964
  /*  proto_tree_add_uint(element_tree, , tvb, offset, 4, num_of_elem); */
1965
2
  EAT(4);
1966
1967
3
  for (i = 0; i < num_of_elem; i++)
1968
1
    {
1969
1
      int new_length;
1970
1971
1
      new_length=dissect_wccp2_mask_value_set_element(tvb, offset, length, i, pinfo, element_tree, addr_table);
1972
1973
2
      CHECK_LENGTH_ADVANCE_OFFSET(new_length);
1974
2
    }
1975
1976
2
  proto_item_set_len(te, offset-start);
1977
2
  return length;
1978
2
}
1979
1980
1981
1982
1983
1984
/* 6.15 Mask Element */
1985
static int
1986
dissect_wccp2_mask_element(tvbuff_t *tvb, int offset, int length, packet_info *pinfo _U_, proto_tree *info_tree)
1987
6
{
1988
6
  if (length < 2)
1989
0
    return length-12;
1990
1991
6
  proto_tree_add_item(info_tree, hf_mask_element_src_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1992
6
  EAT_AND_CHECK(4,4);
1993
6
  proto_tree_add_item(info_tree, hf_mask_element_dest_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1994
1995
6
  EAT_AND_CHECK(4,2);
1996
6
  proto_tree_add_item(info_tree, hf_mask_element_src_port, tvb, offset, 2, ENC_BIG_ENDIAN);
1997
6
  EAT_AND_CHECK(2,2);
1998
6
  proto_tree_add_item(info_tree, hf_mask_element_dest_port, tvb, offset, 2, ENC_BIG_ENDIAN);
1999
6
  EAT(2);
2000
2001
6
  return length;
2002
6
}
2003
2004
2005
2006
2007
2008
2009
/* 6.17 Alternate Mask/Value Set List */
2010
static int dissect_wccp2_alternate_mask_value_set_list(tvbuff_t *tvb, int offset,
2011
                                                        int length, packet_info *pinfo, proto_tree *info_tree, wccp_address_table* addr_table)
2012
2
{
2013
2
  proto_tree *list_tree;
2014
2
  unsigned num_of_val_elements;
2015
2
  unsigned i;
2016
2017
2
  if (length < 4)
2018
0
    return length - 4;
2019
2020
2
  list_tree = proto_tree_add_subtree(info_tree, tvb, offset, length,
2021
2
                               ett_alternate_mask_value_set, NULL, "Alternate Mask/Value Set List");
2022
2023
2
  num_of_val_elements = tvb_get_ntohl(tvb, offset);
2024
2
  proto_tree_add_uint(list_tree, hf_alt_assignment_mask_value_set_list_num_elements, tvb, offset, 4, num_of_val_elements);
2025
2
  EAT(4);
2026
2027
5
  for(i=0;i<num_of_val_elements;i++) {
2028
5
    int new_length;
2029
2030
5
    new_length=dissect_wccp2_alternate_mask_value_set_element(tvb, offset, length, i, pinfo, list_tree, addr_table);
2031
2032
6
    CHECK_LENGTH_ADVANCE_OFFSET(new_length);
2033
6
  }
2034
0
  return length;
2035
2
}
2036
2037
2038
/* 6.18 Alternate Mask/Value Set Element */
2039
static int
2040
dissect_wccp2_alternate_mask_value_set_element(tvbuff_t *tvb, int offset, int length, unsigned el_index, packet_info *pinfo,
2041
                    proto_tree *info_tree, wccp_address_table* addr_table)
2042
5
{
2043
5
  proto_item *tl, *header;
2044
5
  proto_tree *element_tree, *value_tree;
2045
5
  unsigned number_of_elements;
2046
5
  int new_length;
2047
5
  unsigned i;
2048
2049
5
  element_tree = proto_tree_add_subtree_format(info_tree, tvb, offset, 0,
2050
5
                               ett_alternate_mask_value_set_element, &header,
2051
5
                               "Alternate Mask/Value Set Element(%d)", el_index);
2052
2053
5
  new_length=dissect_wccp2_mask_element(tvb,offset,length,pinfo,element_tree);
2054
10
  CHECK_LENGTH_ADVANCE_OFFSET(new_length);
2055
2056
10
  if (length < 4)
2057
0
    return length - 4;
2058
2059
5
  number_of_elements  = tvb_get_ntohl(tvb, offset);
2060
5
  tl = proto_tree_add_uint(element_tree, hf_alt_assignment_mask_value_set_element_num_wc_value_elements, tvb, offset, 4, number_of_elements);
2061
5
  value_tree = proto_item_add_subtree(tl, ett_alternate_mv_set_element_list);
2062
5
  EAT(4);
2063
2064
  /* XXX Add a bounds check for number_of_elements? */
2065
5
  for (i=0; i < number_of_elements; i++) {
2066
2
    new_length=dissect_wccp2_web_cache_value_element(tvb, offset, length, pinfo, value_tree, addr_table);
2067
2
    CHECK_LENGTH_ADVANCE_OFFSET(new_length);
2068
1
  }
2069
3
  proto_item_set_end(header, tvb, offset);
2070
2071
3
  return length;
2072
5
}
2073
2074
/* 6.19 Web-Cache Value Element */
2075
static int
2076
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)
2077
2
{
2078
2
  unsigned number_of_elements, seq_num;
2079
2
  proto_item *tl;
2080
2
  proto_tree *element_tree;
2081
2
  unsigned i;
2082
2083
2
  if (length < 4)
2084
0
    return length - 8;
2085
2086
2
  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);
2087
2088
2
  element_tree = proto_item_add_subtree(tl, ett_web_cache_value_element_list);
2089
2
  EAT_AND_CHECK(4,4);
2090
2091
2
  number_of_elements  = tvb_get_ntohl(tvb, offset);
2092
2
  proto_tree_add_uint(element_tree, hf_web_cache_value_element_num_values, tvb, offset, 4, number_of_elements);
2093
2
  EAT(4);
2094
2095
56
  for (i=0; i < number_of_elements; i++) {
2096
56
    if (length < 4)
2097
2
      return length - 4*(number_of_elements-i);
2098
2099
54
    seq_num = tvb_get_ntohl(tvb, offset);
2100
54
    proto_tree_add_uint_format(element_tree, hf_web_cache_value_seq_num, tvb, offset, 4,
2101
54
                        seq_num, "Value Sequence Number %d: %x", i+1, seq_num);
2102
54
    EAT(4);
2103
54
  }
2104
2105
0
  return length;
2106
2
}
2107
2108
2109
/* End of standard functions */
2110
2111
2112
static void
2113
dissect_32_bit_capability_flags(tvbuff_t *tvb, int curr_offset,
2114
                                uint16_t capability_val_len, int ett, const capability_flag *flags,
2115
                                proto_tree *element_tree, proto_item *header,
2116
                                proto_item *length_item, packet_info *pinfo)
2117
0
{
2118
0
  uint32_t capability_val;
2119
0
  proto_item *tm;
2120
0
  proto_tree *method_tree;
2121
0
  int i;
2122
0
  bool first = true;
2123
2124
0
  if (capability_val_len != 4) {
2125
0
    expert_add_info_format(pinfo, length_item, &ei_wccp_capability_element_length,
2126
0
                "Value Length: %u (illegal, must be == 4)", capability_val_len);
2127
0
    return;
2128
0
  }
2129
2130
0
  capability_val = tvb_get_ntohl(tvb, curr_offset + 4);
2131
0
  tm = proto_tree_add_uint(element_tree, hf_capability_info_value, tvb, curr_offset + 4, 4, capability_val);
2132
2133
0
  for (i = 0; flags[i].short_name != NULL; i++) {
2134
0
    if (capability_val & flags[i].value) {
2135
0
      if (first) {
2136
0
        proto_item_append_text( tm, " (%s", flags[i].short_name);
2137
0
        proto_item_append_text( header, " (%s", flags[i].short_name);
2138
0
        first = false;
2139
0
      } else {
2140
0
        proto_item_append_text( tm, ", %s", flags[i].short_name);
2141
0
        proto_item_append_text( header, " (%s", flags[i].short_name);
2142
0
      }
2143
0
    }
2144
0
  }
2145
2146
0
  if (first == false) {
2147
0
    proto_item_append_text( tm, ")");
2148
0
    proto_item_append_text( header, ")");
2149
0
  }
2150
2151
0
  method_tree = proto_item_add_subtree(tm, ett);
2152
0
  for (i = 0; flags[i].phf != NULL; i++)
2153
0
    proto_tree_add_item(method_tree, *(flags[i].phf), tvb, curr_offset+4, 4, ENC_BIG_ENDIAN);
2154
0
}
2155
2156
2157
2158
/* 6.11.4 Capability Type WCCP2_TRANSMIT_T */
2159
static void
2160
dissect_transmit_t_capability(tvbuff_t *tvb, proto_item *te, int curr_offset,
2161
                              uint16_t capability_val_len, int ett, proto_tree *element_tree,
2162
                              proto_item *length_item, packet_info *pinfo)
2163
0
{
2164
0
  uint16_t upper_limit, lower_limit;
2165
0
  proto_tree *method_tree;
2166
2167
0
  if (capability_val_len != 4) {
2168
0
    expert_add_info_format(pinfo, length_item, &ei_wccp_capability_element_length,
2169
0
                "Value Length: %u (illegal, must be == 4)", capability_val_len);
2170
0
    return;
2171
0
  }
2172
2173
0
  upper_limit = tvb_get_ntohs(tvb, curr_offset);
2174
0
  lower_limit = tvb_get_ntohs(tvb, curr_offset + 2);
2175
2176
0
  if ( upper_limit == 0) {
2177
0
    method_tree = proto_tree_add_subtree(element_tree, tvb, curr_offset, 2,
2178
0
                             ett, NULL, "Only accepting one value");
2179
0
    proto_tree_add_uint(method_tree, hf_reserved_zero, tvb, curr_offset, 2, upper_limit);
2180
2181
0
    proto_tree_add_item(method_tree, hf_capability_transmit_t , tvb, curr_offset+2, 2, ENC_BIG_ENDIAN);
2182
0
    proto_item_append_text(te, " %d ms", lower_limit);
2183
0
  } else {
2184
0
    method_tree = proto_tree_add_subtree(element_tree, tvb, curr_offset, 2,
2185
0
                             ett, NULL, "Accepting a range");
2186
0
    proto_tree_add_item(method_tree, hf_capability_transmit_t_upper_limit,
2187
0
                        tvb, curr_offset, 2, ENC_BIG_ENDIAN);
2188
2189
0
    proto_tree_add_item(method_tree, hf_capability_transmit_t_lower_limit,
2190
0
                        tvb, curr_offset+2, 2, ENC_BIG_ENDIAN);
2191
0
    proto_item_append_text(te, " < %d ms > %d ms", lower_limit, upper_limit);
2192
0
  }
2193
0
}
2194
2195
2196
static void
2197
dissect_timer_scale_capability(tvbuff_t *tvb, int curr_offset,
2198
                               uint16_t capability_val_len, int ett, proto_tree *element_tree,
2199
                               proto_item *length_item, packet_info *pinfo)
2200
0
{
2201
0
  uint8_t a,c;
2202
0
  proto_tree *method_tree;
2203
2204
0
  if (capability_val_len != 4) {
2205
0
    expert_add_info_format(pinfo, length_item, &ei_wccp_capability_element_length,
2206
0
                "Value Length: %u (illegal, must be == 4)", capability_val_len);
2207
0
    return;
2208
0
  }
2209
2210
0
  a = tvb_get_uint8(tvb, curr_offset);
2211
0
  c = tvb_get_uint8(tvb, curr_offset+2);
2212
2213
0
  if ( a == 0) {
2214
0
    if ( c == 0) {
2215
0
      method_tree = proto_tree_add_subtree(element_tree, tvb, curr_offset, 2,
2216
0
                               ett, NULL, "Only accepting one value");
2217
2218
0
      proto_tree_add_uint(method_tree, hf_reserved_zero, tvb, curr_offset, 1, a);
2219
2220
0
      proto_tree_add_item(method_tree, hf_capability_timer_scale_timeout_scale,
2221
0
                          tvb, curr_offset+1, 1, ENC_BIG_ENDIAN);
2222
0
      proto_tree_add_uint(method_tree, hf_reserved_zero, tvb, curr_offset+2, 1, c);
2223
0
      proto_tree_add_item(method_tree, hf_capability_timer_scale_ra_timer_scale,
2224
0
                          tvb, curr_offset+3, 1, ENC_BIG_ENDIAN);
2225
0
    } else {
2226
0
      proto_tree_add_expert(element_tree, pinfo, &ei_wccp_a_zero_not_c, tvb, curr_offset, 1);
2227
0
    }
2228
0
  } else {
2229
0
    if ( c == 0) {
2230
0
      proto_tree_add_expert(element_tree, pinfo, &ei_wccp_a_zero_not_c, tvb, curr_offset, 1);
2231
0
    } else {
2232
0
      method_tree = proto_tree_add_subtree(element_tree, tvb, curr_offset, 2,
2233
0
                               ett, NULL, "Accepting a range");
2234
0
      proto_tree_add_item(method_tree, hf_capability_timer_scale_timeout_scale_upper_limit,
2235
0
                          tvb, curr_offset, 1, ENC_BIG_ENDIAN);
2236
2237
0
      proto_tree_add_item(method_tree, hf_capability_timer_scale_timeout_scale_lower_limit,
2238
0
                          tvb, curr_offset+1, 1, ENC_BIG_ENDIAN);
2239
0
      proto_tree_add_item(method_tree, hf_capability_timer_scale_ra_scale_upper_limit,
2240
0
                          tvb, curr_offset+2, 1, ENC_BIG_ENDIAN);
2241
0
      proto_tree_add_item(method_tree, hf_capability_timer_scale_ra_scale_lower_limit,
2242
0
                          tvb, curr_offset+3, 1, ENC_BIG_ENDIAN);
2243
0
    }
2244
0
  }
2245
0
}
2246
2247
2248
/* 6.16 Value Element */
2249
static int
2250
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)
2251
8
{
2252
8
  proto_tree *element_tree;
2253
2254
8
  if (length < 4)
2255
0
    return length - 16;
2256
2257
8
  element_tree = proto_tree_add_subtree_format(info_tree, tvb, offset, 16, ett_value_element, NULL, "Value Element(%u) %s",
2258
8
                           idx,decode_wccp_encoded_address(tvb, offset+4+4+2+2, pinfo, info_tree, addr_table));
2259
2260
2261
8
  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);
2262
8
  EAT_AND_CHECK(4,4);
2263
8
  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);
2264
2265
8
  EAT_AND_CHECK(4,2);
2266
8
  proto_tree_add_item(element_tree, hf_value_element_src_port, tvb, offset, 2, ENC_BIG_ENDIAN);
2267
8
  EAT_AND_CHECK(2,2);
2268
8
  proto_tree_add_item(element_tree, hf_value_element_dest_port, tvb, offset, 2, ENC_BIG_ENDIAN);
2269
8
  EAT_AND_CHECK(2,4);
2270
2271
8
  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);
2272
8
  EAT(4);
2273
2274
8
  return length;
2275
8
}
2276
2277
2278
/* 6.14 Mask/Value Set Element */
2279
static int
2280
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)
2281
1
{
2282
1
  proto_item *tl, *te;
2283
1
  proto_tree *element_tree, *value_tree;
2284
1
  unsigned num_of_val_elements;
2285
1
  unsigned i;
2286
1
  int new_length;
2287
2288
1
  element_tree = proto_tree_add_subtree_format(info_tree, tvb, offset, 0,
2289
1
                           ett_mv_set_element, &tl, "Mask/Value Set Element(%d)", idx);
2290
2291
1
  new_length = dissect_wccp2_mask_element(tvb,offset,length,pinfo,element_tree);
2292
2
  CHECK_LENGTH_ADVANCE_OFFSET(new_length);
2293
2294
2
  if (length < 4)
2295
0
    return length-4;
2296
2297
1
  num_of_val_elements = tvb_get_ntohl(tvb, offset);
2298
1
  te = proto_tree_add_uint(element_tree, hf_mask_value_set_element_value_element_num, tvb, offset, 4, num_of_val_elements);
2299
2300
1
  value_tree = proto_item_add_subtree(te, ett_mv_set_value_list);
2301
1
  EAT(4);
2302
2303
9
  for (i = 0; i < num_of_val_elements; i++)
2304
8
    {
2305
8
      new_length=dissect_wccp2_value_element(tvb, offset, length, i, pinfo,  value_tree, addr_table);
2306
2307
16
      CHECK_LENGTH_ADVANCE_OFFSET(new_length);
2308
16
    }
2309
2310
1
  proto_item_set_len(tl, 16+num_of_val_elements*16);
2311
2312
1
  return length;
2313
1
}
2314
2315
3
#define ALT_ASSIGNMENT_INFO_MIN_LEN    (4+4)
2316
2317
/* 5.4.2 Alternate Assignment Component */
2318
static int
2319
dissect_wccp2_alternate_assignment_info(tvbuff_t *tvb, int offset, int length,
2320
                                        packet_info *pinfo, proto_tree *info_tree, wccp_address_table* addr_table)
2321
3
{
2322
3
  uint16_t assignment_type;
2323
3
  uint16_t assignment_length;
2324
3
  proto_item *tf=NULL;
2325
2326
3
  uint32_t n_routers;
2327
3
  unsigned i;
2328
3
  proto_tree *element_tree;
2329
3
  int new_length;
2330
2331
2332
3
  if (length < ALT_ASSIGNMENT_INFO_MIN_LEN)
2333
0
    return length - ALT_ASSIGNMENT_INFO_MIN_LEN;
2334
2335
3
  proto_tree_add_item_ret_uint16(info_tree, hf_alt_assignment_info_assignment_type, tvb, offset, 2, ENC_BIG_ENDIAN, &assignment_type);
2336
3
  EAT_AND_CHECK(2,2);
2337
2338
3
  tf=proto_tree_add_item_ret_uint16(info_tree, hf_alt_assignment_info_assignment_length, tvb, offset, 2, ENC_BIG_ENDIAN, &assignment_length);
2339
3
  EAT(2);
2340
2341
3
  if (length < assignment_length)
2342
1
    expert_add_info_format(pinfo, tf, &ei_wccp_assignment_length_bad,
2343
1
                           "Assignment length is %d but only %d remain in the packet. Ignoring this for now",
2344
1
                           assignment_length, length);
2345
2346
3
  if (length > assignment_length)  {
2347
2
    expert_add_info_format(pinfo, tf, &ei_wccp_assignment_length_bad,
2348
2
                           "Assignment length is %d but %d remain in the packet. Assuming that the assignment length is wrong and setting it to %d.",
2349
2
                           assignment_length, length, length);
2350
2
  }
2351
2352
3
  new_length=dissect_wccp2_assignment_key_element(tvb, offset, length, pinfo,  info_tree, addr_table);
2353
6
  CHECK_LENGTH_ADVANCE_OFFSET(new_length);
2354
2355
6
  n_routers = tvb_get_ntohl(tvb, offset);
2356
6
  proto_tree_add_uint(info_tree, hf_alt_assignment_info_num_routers, tvb, offset, 4, n_routers);
2357
6
  EAT(4);
2358
2359
79
  for (i = 0; i < n_routers; i++) {
2360
76
    if (length < 12)
2361
0
      return length - 12*(n_routers-i);
2362
2363
76
    element_tree = proto_tree_add_subtree_format(info_tree, tvb, offset, 12,
2364
76
                             ett_router_alt_assignment_element, NULL,
2365
76
                             "Router %d Assignment Element: IP address %s", i,
2366
76
                             decode_wccp_encoded_address(tvb, offset, pinfo, info_tree, addr_table));
2367
2368
76
    dissect_wccp2_router_assignment_element(tvb, offset, length , pinfo, element_tree, addr_table);
2369
76
    EAT(12);
2370
76
  }
2371
2372
3
  switch (assignment_type) {
2373
1
  case WCCP2_HASH_ASSIGNMENT_TYPE:
2374
1
    return dissect_wccp2_hash_assignment_info(tvb, offset, length,
2375
1
                                              pinfo, info_tree, addr_table);
2376
0
  case WCCP2_MASK_ASSIGNMENT_TYPE:
2377
0
    return dissect_wccp2_mask_value_set_list(tvb, offset, length,
2378
0
                                             pinfo, info_tree, addr_table);
2379
1
  case WCCP2r1_ALT_MASK_ASSIGNMENT_TYPE:
2380
1
    return dissect_wccp2_alternate_mask_value_set_list(tvb, offset, length,
2381
1
                                                       pinfo, info_tree, addr_table);
2382
0
  default:
2383
0
    return length;
2384
3
  }
2385
3
}
2386
2387
static void
2388
dissect_wccp2_info(tvbuff_t *tvb, int offset,
2389
                   packet_info *pinfo, proto_tree *wccp_tree,
2390
                   uint32_t message_type)
2391
12
{
2392
12
  uint16_t type;
2393
12
  uint16_t item_length;
2394
12
  proto_item *tf;
2395
12
  proto_tree *info_tree;
2396
12
  int ett;
2397
12
  int (*dissector)(tvbuff_t *, int, int, packet_info *, proto_tree *, wccp_address_table*);
2398
2399
  /* check if all required fields are there */
2400
12
  bool wccp2_security_info;
2401
12
  bool wccp2_service_info;
2402
12
  bool wccp2_router_id_info;
2403
12
  bool wccp2_wc_id_info;
2404
12
  bool wccp2_rtr_view_info;
2405
12
  bool wccp2_wc_view_info;
2406
12
  bool wccp2_redirect_assignment;
2407
12
  bool wccp2_query_info;
2408
12
  bool wccp2_capabilities_info;
2409
12
  bool wccp2_alt_assignment;
2410
12
  bool wccp2_assign_map;
2411
12
  bool wccp2_command_extension;
2412
12
  bool wccp2r1_alt_assignment_map;
2413
12
  wccp_address_table wccp_wccp_address_table = {false, -1, -1, 0, NULL, NULL};
2414
2415
12
  wccp2_security_info=false;
2416
12
  wccp2_service_info=false;
2417
12
  wccp2_router_id_info=false;
2418
12
  wccp2_wc_id_info=false;
2419
12
  wccp2_rtr_view_info=false;
2420
12
  wccp2_wc_view_info=false;
2421
12
  wccp2_redirect_assignment=false;
2422
12
  wccp2_query_info=false;
2423
12
  wccp2_capabilities_info=false;
2424
12
  wccp2_alt_assignment=false;
2425
12
  wccp2_assign_map=false;
2426
12
  wccp2_command_extension=false;
2427
12
  wccp2r1_alt_assignment_map=false;
2428
2429
  /* ugly hack: we first need to check for the address table
2430
     component, otherwise we cannot print the IP's.
2431
  */
2432
12
  find_wccp_address_table(tvb,offset,pinfo,wccp_tree, &wccp_wccp_address_table);
2433
2434
77
  while (tvb_reported_length_remaining(tvb, offset) > 0) {
2435
65
    type = tvb_get_ntohs(tvb, offset);
2436
65
    switch (type) {
2437
2438
39
    case WCCP2_SECURITY_INFO:
2439
39
      wccp2_security_info=true;
2440
39
      ett = ett_security_info;
2441
39
      dissector = dissect_wccp2_security_info;
2442
39
      break;
2443
2444
0
    case WCCP2_SERVICE_INFO:
2445
0
      wccp2_service_info=true;
2446
0
      ett = ett_service_info;
2447
0
      dissector = dissect_wccp2_service_info;
2448
0
      break;
2449
2450
1
    case WCCP2_ROUTER_ID_INFO:
2451
1
      wccp2_router_id_info=true;
2452
1
      ett = ett_router_identity_info;
2453
1
      dissector = dissect_wccp2_router_identity_info;
2454
1
      break;
2455
2456
0
    case WCCP2_WC_ID_INFO:
2457
0
      wccp2_wc_id_info=true;
2458
0
      ett = ett_wc_identity_info;
2459
0
      dissector = dissect_wccp2_wc_identity_info;
2460
0
      break;
2461
2462
1
    case WCCP2_RTR_VIEW_INFO:
2463
1
      wccp2_rtr_view_info=true;
2464
1
      ett = ett_router_view_info;
2465
1
      dissector = dissect_wccp2_router_view_info;
2466
1
      break;
2467
2468
7
    case WCCP2_WC_VIEW_INFO:
2469
7
      wccp2_wc_view_info=true;
2470
7
      ett = ett_wc_view_info;
2471
7
      dissector = dissect_wccp2_web_cache_view_info;
2472
7
      break;
2473
2474
0
    case WCCP2_REDIRECT_ASSIGNMENT:
2475
0
      wccp2_redirect_assignment=true;
2476
0
      ett = ett_router_assignment_info;
2477
0
      dissector = dissect_wccp2_assignment_info;
2478
0
      break;
2479
2480
0
    case WCCP2_QUERY_INFO:
2481
0
      wccp2_query_info=true;
2482
0
      ett = ett_query_info;
2483
0
      dissector = dissect_wccp2_router_query_info;
2484
0
      break;
2485
2486
3
    case WCCP2_CAPABILITIES_INFO:
2487
3
      wccp2_capabilities_info=true;
2488
3
      ett = ett_capabilities_info;
2489
3
      dissector = dissect_wccp2_capability_info;
2490
3
      break;
2491
2492
3
    case WCCP2_ALT_ASSIGNMENT:
2493
3
      wccp2_alt_assignment=true;
2494
3
      ett = ett_alt_assignment_info;
2495
3
      dissector = dissect_wccp2_alternate_assignment_info;
2496
3
      break;
2497
2498
1
    case WCCP2r1_ALT_ASSIGNMENT_MAP:
2499
1
      wccp2r1_alt_assignment_map=true;
2500
1
      ett = ett_alt_assignment_map;
2501
1
      dissector = dissect_wccp2r1_alt_assignment_map_info;
2502
1
      break;
2503
2504
4
    case WCCP2r1_ADDRESS_TABLE:
2505
4
      ett = ett_address_table;
2506
4
      dissector = dissect_wccp2r1_address_table_info;
2507
4
      break;
2508
2509
0
    case WCCP2_ASSIGN_MAP:
2510
0
      wccp2_assign_map=true;
2511
0
      ett = ett_assignment_map;
2512
0
      dissector = dissect_wccp2_assignment_map;
2513
0
      break;
2514
0
    case WCCP2_COMMAND_EXTENSION:
2515
0
      wccp2_command_extension=true;
2516
0
      ett = ett_command_extension;
2517
0
      dissector = dissect_wccp2_command_extension;
2518
0
      break;
2519
2520
6
    default:
2521
6
      ett = ett_unknown_info;
2522
6
      dissector = NULL;
2523
6
      break;
2524
65
    }
2525
2526
65
    info_tree = proto_tree_add_subtree(wccp_tree, tvb, offset, -1, ett, &tf,
2527
65
                             val_to_str(pinfo->pool, type, info_type_vals, "Unknown info type (%u)"));
2528
2529
65
    proto_tree_add_item(info_tree, hf_item_type, tvb, offset, 2, ENC_BIG_ENDIAN);
2530
2531
65
    proto_tree_add_item_ret_uint16(info_tree, hf_item_length, tvb, offset+2, 2, ENC_BIG_ENDIAN, &item_length);
2532
2533
65
    offset += 4;
2534
2535
65
    if (dissector != NULL) {
2536
59
      int remaining_item_length = (*dissector)(tvb, offset, item_length, pinfo, info_tree, &wccp_wccp_address_table);
2537
2538
      /* warn if we left bytes */
2539
59
      if (remaining_item_length > 0)
2540
6
        expert_add_info_format(pinfo, tf, &ei_wccp_length_bad,
2541
6
                               "The item is %d bytes too long",
2542
6
                               remaining_item_length);
2543
2544
      /* error if we needed more bytes */
2545
59
      if (remaining_item_length < 0)
2546
44
        expert_add_info_format(pinfo, tf, &ei_wccp_length_bad,
2547
44
                               "The item is %d bytes too short",
2548
44
                               -remaining_item_length);
2549
2550
      /* we assume that the item length is correct and jump forward */
2551
59
    } else {
2552
6
      proto_tree_add_item(info_tree, hf_item_data, tvb, offset, item_length, ENC_NA);
2553
6
    }
2554
2555
65
    offset += item_length;
2556
65
    proto_item_set_end(tf, tvb, offset);
2557
65
  }
2558
2559
2560
  /* we're done. Check if we got all the required components */
2561
2562
12
  switch (message_type) {
2563
0
  case WCCP2_HERE_I_AM:
2564
0
    if (!wccp2_security_info)
2565
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_security_info);
2566
0
    if (!wccp2_service_info)
2567
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_service_info);
2568
0
    if (wccp2_router_id_info)
2569
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_router_id_info);
2570
0
    if (!wccp2_wc_id_info)
2571
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_wc_id_info);
2572
0
    if (wccp2_rtr_view_info)
2573
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_rtr_view_info);
2574
0
    if (!wccp2_wc_view_info)
2575
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_wc_view_info);
2576
0
    if (wccp2_redirect_assignment)
2577
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_redirect_assignment);
2578
0
    if (wccp2_query_info)
2579
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_query_info);
2580
0
    if (wccp2_alt_assignment)
2581
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_alt_assignment);
2582
0
    if (wccp2_assign_map)
2583
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_assign_map);
2584
0
    if (wccp2r1_alt_assignment_map)
2585
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_alt_assignment_map);
2586
0
    break;
2587
0
  case WCCP2_I_SEE_YOU:
2588
0
    if (!wccp2_security_info)
2589
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_security_info);
2590
0
    if (!wccp2_service_info)
2591
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_service_info);
2592
0
    if (!wccp2_router_id_info)
2593
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_router_id_info);
2594
0
    if (wccp2_wc_id_info)
2595
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_wc_id_info);
2596
0
    if (!wccp2_rtr_view_info)
2597
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_rtr_view_info);
2598
0
    if (wccp2_wc_view_info)
2599
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_wc_view_info);
2600
0
    if (wccp2_redirect_assignment)
2601
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_redirect_assignment);
2602
0
    if (wccp2_query_info)
2603
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_query_info);
2604
0
    if (wccp2r1_alt_assignment_map)
2605
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_alt_assignment_map);
2606
0
    break;
2607
2608
0
  case WCCP2_REMOVAL_QUERY:
2609
0
    if (!wccp2_security_info)
2610
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_security_info);
2611
0
    if (!wccp2_service_info)
2612
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_service_info);
2613
0
    if (wccp2_router_id_info)
2614
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_router_id_info);
2615
0
    if (wccp2_wc_id_info)
2616
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_wc_id_info);
2617
0
    if (wccp2_rtr_view_info)
2618
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_rtr_view_info);
2619
0
    if (wccp2_wc_view_info)
2620
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_wc_view_info);
2621
0
    if (wccp2_redirect_assignment)
2622
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_redirect_assignment);
2623
0
    if (!wccp2_query_info)
2624
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_query_info);
2625
0
    if (wccp2_capabilities_info)
2626
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_capabilities_info);
2627
0
    if (wccp2_alt_assignment)
2628
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_alt_assignment);
2629
0
    if (wccp2_assign_map)
2630
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_assign_map);
2631
0
    if (wccp2_command_extension)
2632
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_command_extension);
2633
0
    if (wccp2r1_alt_assignment_map)
2634
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_alt_assignment_map);
2635
0
    break;
2636
2637
0
  case WCCP2_REDIRECT_ASSIGN:
2638
0
    if (!wccp2_security_info)
2639
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_security_info);
2640
0
    if (!wccp2_service_info)
2641
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_service_info);
2642
0
    if (wccp2_router_id_info)
2643
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_router_id_info);
2644
0
    if (wccp2_wc_id_info)
2645
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_wc_id_info);
2646
0
    if (wccp2_rtr_view_info)
2647
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_rtr_view_info);
2648
0
    if (wccp2_wc_view_info)
2649
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_wc_view_info);
2650
0
    if (wccp2_query_info)
2651
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_query_info);
2652
0
    if (wccp2_capabilities_info)
2653
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_capabilities_info);
2654
0
    if (! (wccp2_assign_map || wccp2r1_alt_assignment_map || wccp2_alt_assignment || wccp2_redirect_assignment))
2655
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_assignment);
2656
0
    if (wccp2_command_extension)
2657
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_command_extension);
2658
0
    break;
2659
12
  }
2660
12
}
2661
2662
static int
2663
dissect_wccp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
2664
17
{
2665
17
  int offset = 0;
2666
17
  proto_tree *wccp_tree = NULL;
2667
17
  proto_item *wccp_tree_item;
2668
17
  uint32_t wccp_message_type;
2669
17
  uint16_t length;
2670
17
  unsigned wccp2_length;
2671
17
  proto_item *length_item;
2672
17
  uint32_t cache_count;
2673
17
  uint32_t ipaddr;
2674
17
  unsigned i;
2675
17
  uint8_t bucket;
2676
2677
17
  wccp_message_type = tvb_get_ntohl(tvb, offset);
2678
2679
  /* Check if this is really a WCCP message */
2680
17
  if (try_val_to_str(wccp_message_type, wccp_type_vals) == NULL)
2681
3
    return 0;
2682
2683
14
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "WCCP");
2684
2685
14
  col_add_str(pinfo->cinfo, COL_INFO, val_to_str(pinfo->pool, wccp_message_type,
2686
14
                                                   wccp_type_vals, "Unknown WCCP message (%u)"));
2687
2688
14
  wccp_tree_item = proto_tree_add_item(tree, proto_wccp, tvb, offset, -1, ENC_NA);
2689
14
  wccp_tree = proto_item_add_subtree(wccp_tree_item, ett_wccp);
2690
2691
14
  proto_tree_add_uint(wccp_tree, hf_wccp_message_type, tvb, offset, 4, wccp_message_type);
2692
14
  offset += 4;
2693
2694
14
  switch (wccp_message_type) {
2695
2696
0
    case WCCP_HERE_I_AM:
2697
0
      proto_tree_add_item(wccp_tree, hf_wccp_version, tvb,
2698
0
                          offset, 4, ENC_BIG_ENDIAN);
2699
0
      offset += 4;
2700
0
      offset = dissect_hash_data(tvb, offset, wccp_tree);
2701
0
      proto_tree_add_item(wccp_tree, hf_recvd_id, tvb, offset,
2702
0
                          4, ENC_BIG_ENDIAN);
2703
      /*offset += 4;*/
2704
0
      break;
2705
2706
1
    case WCCP_I_SEE_YOU:
2707
1
      proto_tree_add_item(wccp_tree, hf_wccp_version, tvb,
2708
1
                          offset, 4, ENC_BIG_ENDIAN);
2709
1
      offset += 4;
2710
1
      proto_tree_add_item(wccp_tree, hf_change_num, tvb, offset,
2711
1
                          4, ENC_BIG_ENDIAN);
2712
1
      offset += 4;
2713
1
      proto_tree_add_item(wccp_tree, hf_recvd_id, tvb, offset,
2714
1
                          4, ENC_BIG_ENDIAN);
2715
1
      offset += 4;
2716
1
      cache_count = tvb_get_ntohl(tvb, offset);
2717
1
      proto_tree_add_uint(wccp_tree, hf_wc_num, tvb, offset, 4, cache_count);
2718
1
      offset += 4;
2719
18
      for (i = 0; i < cache_count; i++) {
2720
17
        offset = dissect_web_cache_list_entry(tvb, offset, i,
2721
17
                                              wccp_tree);
2722
17
      }
2723
1
      break;
2724
2725
1
    case WCCP_ASSIGN_BUCKET:
2726
      /*
2727
       * This hasn't been tested, since I don't have any
2728
       * traces with this in it.
2729
       *
2730
       * The V1 spec claims that this does, indeed,
2731
       * have a Received ID field after the type,
2732
       * rather than a Version field.
2733
       */
2734
1
      proto_tree_add_item(wccp_tree, hf_recvd_id, tvb, offset,
2735
1
                          4, ENC_BIG_ENDIAN);
2736
1
      offset += 4;
2737
1
      cache_count = tvb_get_ntohl(tvb, offset);
2738
1
      proto_tree_add_uint(wccp_tree, hf_wc_num, tvb, offset, 4, cache_count);
2739
1
      offset += 4;
2740
193
      for (i = 0; i < cache_count; i++) {
2741
192
        ipaddr = tvb_get_ipv4(tvb, offset);
2742
192
        proto_tree_add_ipv4_format(wccp_tree,
2743
192
                                   hf_cache_ip, tvb, offset, 4,
2744
192
                                   ipaddr,
2745
192
                                   "Web Cache %d IP Address: %s", i,
2746
192
                                   tvb_ip_to_str(pinfo->pool, tvb, offset));
2747
192
        offset += 4;
2748
192
      }
2749
2750
1
      for (i = 0; i < 256; i++) {
2751
0
          bucket = tvb_get_uint8(tvb, offset);
2752
0
          if (bucket == 0xff) {
2753
0
              proto_tree_add_uint_format(wccp_tree, hf_bucket, tvb, offset, 1,
2754
0
                  bucket, "Bucket %d: Unassigned", i);
2755
0
          } else {
2756
0
              proto_tree_add_uint_format(wccp_tree, hf_bucket, tvb, offset, 1,
2757
0
                    bucket, "Bucket %d: %d", i, bucket);
2758
0
          }
2759
0
        offset++;
2760
0
      }
2761
1
      break;
2762
2763
0
    case WCCP2_HERE_I_AM:
2764
0
    case WCCP2_I_SEE_YOU:
2765
0
    case WCCP2_REMOVAL_QUERY:
2766
12
    case WCCP2_REDIRECT_ASSIGN:
2767
12
    default:    /* assume unknown packets are v2 */
2768
      /* 5.5 WCCP Message Header */
2769
2770
12
      proto_tree_add_item(wccp_tree, hf_message_header_version, tvb, offset, 2,
2771
12
                          ENC_BIG_ENDIAN);
2772
12
      offset += 2;
2773
2774
12
      length = tvb_get_ntohs(tvb, offset);
2775
12
      length_item = proto_tree_add_uint(wccp_tree, hf_message_header_length, tvb, offset, 2, length);
2776
12
      offset += 2;
2777
2778
      /* Is the length plus the length of the data preceding it longer than
2779
         the length of our packet? */
2780
12
      wccp2_length = tvb_reported_length_remaining(tvb, offset);
2781
12
      if (length > wccp2_length) {
2782
12
        expert_add_info_format(pinfo, length_item, &ei_wccp_length_bad,
2783
12
                               "The length as specified by the length field is bigger than the length of the packet");
2784
12
        length = wccp2_length;
2785
12
      } else {
2786
        /* Truncate the packet to the specified length. */
2787
0
        tvb_set_reported_length(tvb, offset + length);
2788
0
      }
2789
12
      proto_item_set_len(wccp_tree_item, offset + length);
2790
12
      dissect_wccp2_info(tvb, offset, pinfo, wccp_tree, wccp_message_type);
2791
12
      break;
2792
14
  }
2793
2794
0
  return tvb_captured_length(tvb);
2795
14
}
2796
2797
2798
2799
/* End of utility functions */
2800
2801
void
2802
proto_register_wccp(void)
2803
16
{
2804
16
  static hf_register_info hf[] = {
2805
16
    { &hf_wccp_message_type,
2806
16
      { "WCCP Message Type", "wccp.message", FT_UINT32, BASE_DEC, VALS(wccp_type_vals), 0x0,
2807
16
        "The WCCP message that was sent", HFILL }
2808
16
    },
2809
16
    { &hf_wccp_version,
2810
16
      { "WCCP Version", "wccp.version", FT_UINT32, BASE_HEX, VALS(wccp_version_val), 0x0,
2811
16
        "The WCCP version", HFILL }
2812
16
    },
2813
16
    { &hf_bucket,
2814
16
      { "Bucket", "wccp.bucket", FT_UINT8, BASE_DEC, 0x0, 0x0,
2815
16
        NULL, HFILL }
2816
16
    },
2817
16
    { &hf_bucket_bit,
2818
16
      { "Bucket", "wccp.bucket_bit", FT_UINT8, BASE_DEC, 0x0, 0x0,
2819
16
        NULL, HFILL }
2820
16
    },
2821
16
    { &hf_message_header_version,
2822
16
      { "WCCP Version (>=2)", "wccp.message_header_version", FT_UINT16, BASE_HEX, NULL, 0x0,
2823
16
        "The WCCP version for version 2 and above", HFILL }
2824
16
    },
2825
16
    { &hf_hash_revision,
2826
16
      { "Hash Revision", "wccp.hash_revision", FT_UINT32, BASE_DEC, 0x0, 0x0,
2827
16
        "The cache hash revision", HFILL }
2828
16
    },
2829
16
    { &hf_change_num,
2830
16
      { "Change Number", "wccp.change_num", FT_UINT32, BASE_DEC, 0x0, 0x0,
2831
16
        "The Web-Cache list entry change number", HFILL }
2832
16
    },
2833
16
    { &hf_hash_flag,
2834
16
      { "Flags", "wccp.hash_flag", FT_UINT32, BASE_HEX, 0x0, 0x0,
2835
16
        NULL, HFILL }
2836
16
    },
2837
16
    { &hf_hash_flag_u,
2838
16
      { "Hash information", "wccp.hash_flag.u", FT_BOOLEAN, 32, TFS(&tfs_historical_current), 0x00010000,
2839
16
        NULL, HFILL }
2840
16
    },
2841
16
    { &hf_recvd_id,
2842
16
      { "Received ID", "wccp.recvd_id", FT_UINT32, BASE_DEC, 0x0, 0x0,
2843
16
        "The number of I_SEE_YOU's that have been sent", HFILL }
2844
16
    },
2845
16
    { &hf_cache_ip,
2846
16
      { "Web Cache IP address", "wccp.cache_ip", FT_IPv4, BASE_NONE, NULL, 0x0,
2847
16
        "The IP address of a Web cache", HFILL }
2848
16
    },
2849
16
    { &hf_wc_num,
2850
16
      { "Number of Web Caches", "wccp.wc_num", FT_UINT32, BASE_DEC, 0x0, 0x0,
2851
16
        NULL, HFILL }
2852
16
    },
2853
16
    { &hf_message_header_length,
2854
16
      { "Length", "wccp.message_header_length", FT_UINT16, BASE_DEC, 0x0, 0x0,
2855
16
        NULL, HFILL }
2856
16
    },
2857
16
    { &hf_item_length,
2858
16
      { "Length", "wccp.item_length", FT_UINT16, BASE_DEC, 0x0, 0x0,
2859
16
        "The Length of the WCCPv2 item", HFILL }
2860
16
    },
2861
16
    { &hf_item_type,
2862
16
      { "Type", "wccp.item_type", FT_UINT16, BASE_DEC, VALS(info_type_vals), 0x0,
2863
16
        "The type of the WCCPv2 item", HFILL }
2864
16
    },
2865
16
    { &hf_item_data,
2866
16
      { "Data", "wccp.item_data", FT_BYTES, BASE_NONE, 0x0, 0x0,
2867
16
        "The data for an unknown item type", HFILL }
2868
16
    },
2869
16
    { &hf_security_info_option,
2870
16
      { "Security Option", "wccp.security_info_option", FT_UINT32, BASE_DEC, VALS(security_option_vals), 0x0,
2871
16
        NULL, HFILL }
2872
16
    },
2873
16
    { &hf_security_info_md5_checksum,
2874
16
      { "MD5 checksum (not checked)", "wccp.security_md5_checksum", FT_BYTES, BASE_NONE, 0x0, 0x0,
2875
16
        NULL, HFILL }
2876
16
    },
2877
16
    { &hf_command_element_type,
2878
16
      {"Command Extension Type", "wccp.command_element_type", FT_UINT16, BASE_DEC, VALS(wccp_command_type_vals), 0x0,
2879
16
       NULL, HFILL }
2880
16
    },
2881
16
    { &hf_command_element_length,
2882
16
      {"Command Extension Length", "wccp.command_element_length", FT_UINT16, BASE_DEC, NULL, 0x0,
2883
16
       NULL, HFILL }
2884
16
    },
2885
16
    { &hf_command_length,
2886
16
      {"Command Length", "wccp.command_length", FT_UINT16, BASE_DEC, NULL, 0x0,
2887
16
       NULL, HFILL }
2888
16
    },
2889
16
    { &hf_command_element_shutdown_ip_index,
2890
16
      {"Command Element Shutdown IP", "wccp.command_element_shutdown_ip_Address.index", FT_UINT32, BASE_HEX, NULL, 0x0,
2891
16
       NULL, HFILL }
2892
16
    },
2893
16
    { &hf_command_element_shutdown_ipv4,
2894
16
      {"Command Element Shutdown IP", "wccp.command_element_shutdown_ip_address.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
2895
16
       NULL, HFILL }
2896
16
    },
2897
16
    { &hf_command_element_shutdown_ipv6,
2898
16
      {"Command Element Shutdown IP", "wccp.command_element_shutdown_ip_address.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
2899
16
       NULL, HFILL }
2900
16
    },
2901
16
    { &hf_command_unknown,
2902
16
      {"Unknown Command", "wccp.command_unknown", FT_NONE, BASE_NONE, NULL, 0x0,
2903
16
       NULL, HFILL }
2904
16
    },
2905
16
    { &hf_service_info_type,
2906
16
      { "Service Type", "wccp.service_info_type", FT_UINT8, BASE_DEC, VALS(service_type_vals), 0x0,
2907
16
        NULL, HFILL }
2908
16
    },
2909
16
    { &hf_service_info_id_standard,
2910
16
      { "WCCP Service ID (Standard)", "wccp.service_info_std_id", FT_UINT8, BASE_DEC, VALS(service_id_vals) , 0x0,
2911
16
        "The WCCP Service id (Standard)", HFILL }
2912
16
    },
2913
16
    { &hf_service_info_id_dynamic,
2914
16
      { "WCCP Service ID ( Dynamic)", "wccp.service_info_dyn_id", FT_UINT8, BASE_DEC, NULL , 0x0,
2915
16
        "The WCCP Service id (Dynamic)", HFILL }
2916
16
    },
2917
16
    { &hf_service_info_priority,
2918
16
      { "Priority (highest is 255)", "wccp.service_info_priority", FT_UINT8, BASE_DEC, NULL, 0x0,
2919
16
        NULL, HFILL }
2920
16
    },
2921
16
    { &hf_service_info_protocol,
2922
16
      { "Protocol", "wccp.service_info_protocol", FT_UINT8, BASE_DEC | BASE_EXT_STRING, &ipproto_val_ext, 0x0,
2923
16
        NULL, HFILL }
2924
16
    },
2925
16
    { &hf_service_info_flags,
2926
16
      { "Flags", "wccp.service_info_flags", FT_UINT32, BASE_HEX, 0x0, 0x0,
2927
16
        NULL, HFILL }
2928
16
    },
2929
16
    { &hf_service_info_flags_src_ip_hash,
2930
16
      { "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,
2931
16
        NULL, HFILL }
2932
16
    },
2933
16
    { &hf_service_info_flags_dest_ip_hash,
2934
16
      { "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,
2935
16
        NULL, HFILL }
2936
16
    },
2937
16
    { &hf_service_info_flags_src_port_hash,
2938
16
      { "Source port in primary hash", "wccp.service_info_flag.src_port_hash", FT_BOOLEAN, 32, TFS(&tfs_used_notused), WCCP2_SI_SRC_PORT_HASH,
2939
16
        NULL, HFILL }
2940
16
    },
2941
16
    { &hf_service_info_flags_dest_port_hash,
2942
16
      { "Destination port in primary hash", "wccp.service_info_flag.dest_port_hash", FT_BOOLEAN, 32, TFS(&tfs_used_notused), WCCP2_SI_DST_PORT_HASH,
2943
16
        NULL, HFILL }
2944
16
    },
2945
16
    { &hf_service_info_flags_ports_defined,
2946
16
      { "Ports", "wccp.service_info_flag.ports_defined", FT_BOOLEAN, 32, TFS(&tfs_defined_not_defined), WCCP2_SI_PORTS_DEFINED,
2947
16
        NULL, HFILL }
2948
16
    },
2949
16
    { &hf_service_info_flags_ports_source,
2950
16
      { "Ports refer to", "wccp.service_info_flag.ports_source", FT_BOOLEAN, 32, TFS(&tfs_src_dest_port), WCCP2_SI_PORTS_SOURCE,
2951
16
        NULL, HFILL }
2952
16
    },
2953
16
    { &hf_service_info_flags_redirect_only_protocol_0,
2954
16
      { "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,
2955
16
        NULL, HFILL }
2956
16
    },
2957
16
    { &hf_service_info_flags_src_ip_alt_hash,
2958
16
      { "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,
2959
16
        NULL, HFILL }
2960
16
    },
2961
16
    { &hf_service_info_flags_dest_ip_alt_hash,
2962
16
      { "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,
2963
16
        NULL, HFILL }
2964
16
    },
2965
16
    { &hf_service_info_flags_src_port_alt_hash,
2966
16
      { "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,
2967
16
        NULL, HFILL }
2968
16
    },
2969
16
    { &hf_service_info_flags_dest_port_alt_hash,
2970
16
      { "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,
2971
16
        NULL, HFILL }
2972
16
    },
2973
16
    { &hf_service_info_flags_reserved,
2974
16
      { "Reserved, should be 0", "wccp.service_info_flag.reserved", FT_UINT32, BASE_HEX, NULL, 0xFFFFF000,
2975
16
        NULL, HFILL }
2976
16
    },
2977
16
    { &hf_service_info_source_port,
2978
16
      { "Source Port", "wccp.service_info_source_port", FT_UINT16, BASE_DEC, NULL, 0x0,
2979
16
        NULL, HFILL }
2980
16
    },
2981
16
    { &hf_service_info_destination_port,
2982
16
      { "Destination Port", "wccp.service_info_destination_port", FT_UINT16, BASE_DEC, NULL, 0x0,
2983
16
        NULL, HFILL }
2984
16
    },
2985
16
    { &hf_router_identity_ip_index,
2986
16
      { "IP Address", "wccp.router_identity.ip_address.index", FT_UINT32, BASE_DEC, NULL, 0x0,
2987
16
        NULL, HFILL }
2988
16
    },
2989
16
    { &hf_router_identity_ipv4,
2990
16
      { "IP Address", "wccp.router_identity.ip_address.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
2991
16
        NULL, HFILL }
2992
16
    },
2993
16
    { &hf_router_identity_ipv6,
2994
16
      { "IP Address", "wccp.router_identity.ip_address.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
2995
16
        NULL, HFILL }
2996
16
    },
2997
16
    { &hf_router_identity_receive_id,
2998
16
      { "Received ID", "wccp.router_identity.receive_id", FT_UINT32, BASE_DEC, 0x0, 0x0,
2999
16
        NULL, HFILL }
3000
16
    },
3001
16
    { &hf_router_identity_send_to_ip_index,
3002
16
      { "Sent To IP Address", "wccp.router_identity.send_to_ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3003
16
        NULL, HFILL }
3004
16
    },
3005
16
    { &hf_router_identity_send_to_ipv4,
3006
16
      { "Sent To IP Address", "wccp.router_identity.send_to_ip.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3007
16
        NULL, HFILL }
3008
16
    },
3009
16
    { &hf_router_identity_send_to_ipv6,
3010
16
      { "Sent To IP Address", "wccp.router_identity.send_to_ip.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3011
16
        NULL, HFILL }
3012
16
    },
3013
16
    { &hf_router_identity_received_from_num,
3014
16
      { "Number of Received From IP addresses (Webcache to which the message is directed)", "wccp.router.num_recv_ip", FT_UINT32, BASE_DEC, 0x0, 0x0,
3015
16
        NULL, HFILL }
3016
16
    },
3017
16
    { &hf_web_cache_identity_index,
3018
16
      { "Web-Cache IP Address", "wccp.web_cache_identity.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3019
16
        NULL, HFILL }
3020
16
    },
3021
16
    { &hf_web_cache_identity_ipv4,
3022
16
      { "Web-Cache IP Address", "wccp.web_cache_identity.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3023
16
        NULL, HFILL }
3024
16
    },
3025
16
    { &hf_web_cache_identity_ipv6,
3026
16
      { "Web-Cache IP Address", "wccp.web_cache_identity.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3027
16
        NULL, HFILL }
3028
16
    },
3029
16
    { &hf_web_cache_identity_hash_rev,
3030
16
      { "Hash Revision", "wccp.web_cache_identity.hash_rev", FT_UINT16, BASE_DEC, NULL, 0x0,
3031
16
        NULL, HFILL }
3032
16
    },
3033
16
    { &hf_web_cache_identity_flags,
3034
16
      { "Flags", "wccp.web_cache_identity.flags", FT_UINT16, BASE_HEX, NULL, 0x0,
3035
16
        NULL, HFILL }
3036
16
    },
3037
16
    { &hf_web_cache_identity_flag_hash_info,
3038
16
      { "Hash information", "wccp.web_cache_identity.flags.hash_info", FT_BOOLEAN, 16,
3039
16
        TFS(&tfs_historical_current), 0x1,
3040
16
        NULL, HFILL }
3041
16
    },
3042
16
    { &hf_web_cache_identity_flag_assign_type,
3043
16
      { "Assignment Type", "wccp.web_cache_identity.flags.assign_type", FT_UINT16, BASE_HEX,
3044
16
        VALS(wccp_web_cache_assignment_data_type_val), 0x6,
3045
16
        NULL, HFILL }
3046
16
    },
3047
16
    { &hf_web_cache_identity_flag_version_request,
3048
16
      { "Version Request", "wccp.web_cache_identity.flags.version_request", FT_BOOLEAN, 16,
3049
16
        TFS(&tfs_version_min_max), 0x8,
3050
16
        NULL, HFILL }
3051
16
    },
3052
16
    { &hf_web_cache_identity_flag_reserved,
3053
16
      { "Reserved, should be 0", "wccp.web_cache_identity.flags.reserved", FT_UINT16, BASE_HEX,
3054
16
        NULL, 0xFFF0,
3055
16
        NULL, HFILL }
3056
16
    },
3057
16
    { &hf_mask_value_set_element_value_element_num,
3058
16
      { "Number of Value Elements", "wccp.mask_value_set_element.value_element_num", FT_UINT32, BASE_DEC, 0x0, 0x0,
3059
16
        NULL, HFILL }
3060
16
    },
3061
16
    { &hf_assignment_weight,
3062
16
      { "Assignment Weight", "wccp.assignment_weight", FT_UINT16, BASE_DEC, NULL, 0x0,
3063
16
        NULL, HFILL }
3064
16
    },
3065
16
    { &hf_assignment_status,
3066
16
      { "Status", "wccp.assignment_status", FT_UINT16, BASE_HEX, NULL, 0x0,
3067
16
        NULL, HFILL }
3068
16
    },
3069
16
    { &hf_assignment_key_ip_index,
3070
16
      { "Assignment Key IP Address", "wccp.assignment_key.ip_index", FT_UINT32, BASE_DEC, NULL, 0x0,
3071
16
        NULL, HFILL }
3072
16
    },
3073
16
    { &hf_assignment_key_ipv4,
3074
16
      { "Assignment Key IP Address", "wccp.assignment_key.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3075
16
        NULL, HFILL }
3076
16
    },
3077
16
    { &hf_assignment_key_ipv6,
3078
16
      { "Assignment Key IP Address", "wccp.assignment_key.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3079
16
        NULL, HFILL }
3080
16
    },
3081
16
    { &hf_assignment_key_change_num,
3082
16
      { "Assignment Key Change Number", "wccp.assignment_key.change_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3083
16
        NULL, HFILL }
3084
16
    },
3085
16
    { &hf_assignment_no_data,
3086
16
      { "No Assignment Data Present", "wccp.assignment_no_data", FT_NONE, BASE_NONE, NULL, 0x0,
3087
16
        NULL, HFILL }
3088
16
    },
3089
16
    { &hf_router_view_member_change_num,
3090
16
      { "Member Change Number", "wccp.router_view.member_change_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3091
16
        NULL, HFILL }
3092
16
    },
3093
16
    { &hf_router_router_num,
3094
16
      { "Number of Routers", "wccp.router_view.router_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3095
16
        NULL, HFILL }
3096
16
    },
3097
16
    { &hf_router_identity_router_ip_index,
3098
16
      { "Router IP Address", "wccp.router_identity.router_ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3099
16
        NULL, HFILL }
3100
16
    },
3101
16
    { &hf_router_identity_router_ipv4,
3102
16
      { "Router IP Address", "wccp.router_identity.router_ip.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3103
16
        NULL, HFILL }
3104
16
    },
3105
16
    { &hf_router_identity_router_ipv6,
3106
16
      { "Router IP Address", "wccp.router_identity.router_ip.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3107
16
        NULL, HFILL }
3108
16
    },
3109
16
    { &hf_router_identity_received_from_ip_index,
3110
16
      { "Received From IP Address/Target Web Cache IP", "wccp.router_identity.received_from_ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3111
16
        NULL, HFILL }
3112
16
    },
3113
16
    { &hf_router_identity_received_from_ipv4,
3114
16
      { "Received From IP Address/Target Web Cache IP", "wccp.router_identity.received_from_ip.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3115
16
        NULL, HFILL }
3116
16
    },
3117
16
    { &hf_router_identity_received_from_ipv6,
3118
16
      { "Received From IP Address/Target Web Cache IP", "wccp.router_identity.received_from_ip.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3119
16
        NULL, HFILL }
3120
16
    },
3121
16
    { &hf_wc_view_info_change_num,
3122
16
      { "Change Number", "wccp.wc_view_info.change_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3123
16
        NULL, HFILL }
3124
16
    },
3125
16
    { &hf_wc_view_info_router_ip_index,
3126
16
      { "Router IP", "wccp.wc_view_info.router_ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3127
16
        NULL, HFILL }
3128
16
    },
3129
16
    { &hf_wc_view_info_router_ipv4,
3130
16
      { "Router IP", "wccp.wc_view_info.router_ip.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3131
16
        NULL, HFILL }
3132
16
    },
3133
16
    { &hf_wc_view_info_router_ipv6,
3134
16
      { "Router IP", "wccp.wc_view_info.router_ip.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3135
16
        NULL, HFILL }
3136
16
    },
3137
16
    { &hf_wc_view_info_wc_ip_index,
3138
16
      { "Web Cache IP", "wccp.wc_view_info.wc_ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3139
16
        NULL, HFILL }
3140
16
    },
3141
16
    { &hf_wc_view_info_wc_ipv4,
3142
16
      { "Web Cache IP", "wccp.wc_view_info.wc_ip.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3143
16
        NULL, HFILL }
3144
16
    },
3145
16
    { &hf_wc_view_info_wc_ipv6,
3146
16
      { "Web Cache IP", "wccp.wc_view_info.wc_ip.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3147
16
        NULL, HFILL }
3148
16
    },
3149
16
    { &hf_wc_view_router_num,
3150
16
      { "Number of Routers", "wccp.wc_view_info.router_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3151
16
        NULL, HFILL }
3152
16
    },
3153
16
    { &hf_wc_view_wc_num,
3154
16
      { "Number of Web Caches", "wccp.wc_view_info.wc_num", FT_UINT32, BASE_DEC, 0x0, 0x0,
3155
16
        NULL, HFILL }
3156
16
    },
3157
16
    { &hf_wc_identity_ip_address_index,
3158
16
      { "Web Cache Identity", "wccp.wc_identity_ip_address.index", FT_UINT32, BASE_DEC, NULL, 0x0,
3159
16
        "The IP identifying the Web Cache", HFILL }
3160
16
    },
3161
16
    { &hf_wc_identity_ip_address_ipv4,
3162
16
      { "Web Cache Identity", "wccp.wc_identity_ip_address.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3163
16
        "The IP identifying the Web Cache", HFILL }
3164
16
    },
3165
16
    { &hf_wc_identity_ip_address_ipv6,
3166
16
      { "Web Cache Identity", "wccp.wc_identity_ip_address.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3167
16
        "The IP identifying the Web Cache", HFILL }
3168
16
    },
3169
16
    { &hf_router_assignment_element_change_num,
3170
16
      { "Change Number", "wccp.router_assignment_element.change_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3171
16
        NULL, HFILL }
3172
16
    },
3173
16
    { &hf_assignment_info_router_num,
3174
16
      { "Number of Routers", "wccp.assignment_info.router_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3175
16
        NULL, HFILL }
3176
16
    },
3177
16
    { &hf_assignment_info_router_ip_index,
3178
16
      { "Router IP", "wccp.assignment_info.router_ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3179
16
        NULL, HFILL }
3180
16
    },
3181
16
    { &hf_assignment_info_router_ipv4,
3182
16
      { "Router IP", "wccp.assignment_info.router_ip.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3183
16
        NULL, HFILL }
3184
16
    },
3185
16
    { &hf_assignment_info_router_ipv6,
3186
16
      { "Router IP", "wccp.assignment_info.router_ip.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3187
16
        NULL, HFILL }
3188
16
    },
3189
16
    { &hf_hash_buckets_assignment_wc_num,
3190
16
      { "Number of WC", "wccp.hash_buckets_assignment.wc_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3191
16
        NULL, HFILL }
3192
16
    },
3193
16
    { &hf_hash_buckets_assignment_wc_ip_index,
3194
16
      { "WC IP", "wccp.hash_buckets_assignment.wc_ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3195
16
        NULL, HFILL }
3196
16
    },
3197
16
    { &hf_hash_buckets_assignment_wc_ipv4,
3198
16
      { "WC IP", "wccp.hash_buckets_assignment.wc_ip.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3199
16
        NULL, HFILL }
3200
16
    },
3201
16
    { &hf_hash_buckets_assignment_wc_ipv6,
3202
16
      { "WC IP", "wccp.hash_buckets_assignment.wc_ip.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3203
16
        NULL, HFILL }
3204
16
    },
3205
16
    { &hf_router_view_ip_index,
3206
16
      { "Router IP Address", "wccp.router_view.ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3207
16
        NULL, HFILL }
3208
16
    },
3209
16
    { &hf_router_view_ipv4,
3210
16
      { "Router IP Address", "wccp.router_view.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3211
16
        NULL, HFILL }
3212
16
    },
3213
16
    { &hf_router_view_ipv6,
3214
16
      { "Router IP Address", "wccp.router_view.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3215
16
        NULL, HFILL }
3216
16
    },
3217
16
    { &hf_router_query_info_ip_index,
3218
16
      { "Web-Cache Identity Element IP address", "wccp.router_query_info.ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3219
16
        NULL, HFILL }
3220
16
    },
3221
16
    { &hf_router_query_info_ipv4,
3222
16
      { "Web-Cache Identity Element IP address", "wccp.router_query_info.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3223
16
        NULL, HFILL }
3224
16
    },
3225
16
    { &hf_router_query_info_ipv6,
3226
16
      { "Web-Cache Identity Element IP address", "wccp.router_query_info.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3227
16
        NULL, HFILL }
3228
16
    },
3229
16
    { &hf_router_query_info_send_to_ip_index,
3230
16
      { "Sent To IP Address", "wccp.router_query_info.send_to_ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3231
16
        NULL, HFILL }
3232
16
    },
3233
16
    { &hf_router_query_info_send_to_ipv4,
3234
16
      { "Sent To IP Address", "wccp.router_query_info.send_to_ip.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3235
16
        NULL, HFILL }
3236
16
    },
3237
16
    { &hf_router_query_info_send_to_ipv6,
3238
16
      { "Sent To IP Address", "wccp.router_query_info.send_to_ip.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3239
16
        NULL, HFILL }
3240
16
    },
3241
16
    { &hf_router_query_info_target_ip_index,
3242
16
      { "Target IP Address", "wccp.router_query_info.target_ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3243
16
        NULL, HFILL }
3244
16
    },
3245
16
    { &hf_router_query_info_target_ipv4,
3246
16
      { "Target IP Address", "wccp.router_query_info.target_ip.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3247
16
        NULL, HFILL }
3248
16
    },
3249
16
    { &hf_router_query_info_target_ipv6,
3250
16
      { "Target IP Address", "wccp.router_query_info.target_ip.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3251
16
        NULL, HFILL }
3252
16
    },
3253
16
    { &hf_capability_element_type,
3254
16
      { "Type", "wccp.capability_element.type", FT_UINT16, BASE_DEC, VALS(capability_type_vals), 0x0,
3255
16
        NULL, HFILL }
3256
16
    },
3257
16
    { &hf_capability_element_length,
3258
16
      { "Value Length", "wccp.capability_element.length", FT_UINT16, BASE_DEC, NULL, 0x0,
3259
16
        NULL, HFILL }
3260
16
    },
3261
16
    { &hf_capability_info_value,
3262
16
      { "Value", "wccp.capability_info.value", FT_UINT32, BASE_HEX, NULL, 0x0,
3263
16
        NULL, HFILL }
3264
16
    },
3265
16
    { &hf_capability_forwarding_method_flag_gre,
3266
16
      { "GRE-encapsulated", "wccp.capability_info.forwarding_method_flag.gre", FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), WCCP2_FORWARDING_METHOD_GRE,
3267
16
        NULL, HFILL }
3268
16
    },
3269
16
    { &hf_capability_forwarding_method_flag_l2,
3270
16
      { "L2 rewrite", "wccp.capability_info.forwarding_method_flag.l2", FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), WCCP2_FORWARDING_METHOD_L2,
3271
16
        NULL, HFILL }
3272
16
    },
3273
16
    { &hf_capability_assignment_method_flag_hash,
3274
16
      { "Hash", "wccp.capability_info.assignment_method_flag.hash", FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), WCCP2_ASSIGNMENT_METHOD_HASH,
3275
16
        NULL, HFILL }
3276
16
    },
3277
16
    { &hf_capability_assignment_method_flag_mask,
3278
16
      { "Mask", "wccp.capability_info.assignment_method_flag.mask", FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), WCCP2_ASSIGNMENT_METHOD_MASK,
3279
16
        NULL, HFILL }
3280
16
    },
3281
16
    { &hf_capability_return_method_flag_gre,
3282
16
      { "GRE-encapsulated", "wccp.capability_info.return_method_flag.gre", FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), WCCP2_PACKET_RETURN_METHOD_GRE,
3283
16
        NULL, HFILL }
3284
16
    },
3285
16
    { &hf_capability_return_method_flag_l2,
3286
16
      { "L2 rewrite", "wccp.capability_info.return_method_flag.l2", FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), WCCP2_PACKET_RETURN_METHOD_L2,
3287
16
        NULL, HFILL }
3288
16
    },
3289
16
    { &hf_capability_transmit_t,
3290
16
      { "Message interval in milliseconds", "wccp.capability.transmit_t", FT_UINT16, BASE_DEC, NULL, 0x0,
3291
16
        NULL, HFILL }
3292
16
    },
3293
16
    { &hf_capability_transmit_t_upper_limit,
3294
16
      { "Message interval upper limit in milliseconds", "wccp.capability.transmit_t.upper_limit", FT_UINT16, BASE_DEC, NULL, 0x0,
3295
16
        NULL, HFILL }
3296
16
    },
3297
16
    { &hf_capability_transmit_t_lower_limit,
3298
16
      { "Message interval lower limit in milliseconds", "wccp.capability.transmit_t.lower_limit", FT_UINT16, BASE_DEC, NULL, 0x0,
3299
16
        NULL, HFILL }
3300
16
    },
3301
16
    { &hf_capability_timer_scale_timeout_scale,
3302
16
      { "Timer scale", "wccp.capability.timer_scale.timeout_scale", FT_UINT8, BASE_DEC, NULL, 0x0,
3303
16
        NULL, HFILL }
3304
16
    },
3305
16
    { &hf_capability_timer_scale_timeout_scale_upper_limit,
3306
16
      { "Timer scale upper limit", "wccp.capability.timer_scale.timeout_scale.upper_limit", FT_UINT8, BASE_DEC, NULL, 0x0,
3307
16
        NULL, HFILL }
3308
16
    },
3309
16
    { &hf_capability_timer_scale_timeout_scale_lower_limit,
3310
16
      { "Timer scale lower limit", "wccp.capability.timer_scale.timeout_scale.lower_limit", FT_UINT8, BASE_DEC, NULL, 0x0,
3311
16
        NULL, HFILL }
3312
16
    },
3313
16
    { &hf_capability_timer_scale_ra_timer_scale,
3314
16
      { "RA Timer scale", "wccp.capability.timer_scale.ra_timer_scale", FT_UINT8, BASE_DEC, NULL, 0x0,
3315
16
        NULL, HFILL }
3316
16
    },
3317
16
    { &hf_capability_timer_scale_ra_scale_upper_limit,
3318
16
      { "RA Timer scale upper limit", "wccp.capability.timer_scale.ra_timer_scale.upper_limit", FT_UINT8, BASE_DEC, NULL, 0x0,
3319
16
        NULL, HFILL }
3320
16
    },
3321
16
    { &hf_capability_timer_scale_ra_scale_lower_limit,
3322
16
      { "RA Timer scale lower limit", "wccp.capability.timer_scale.ra_timer_scale.lower_limit", FT_UINT8, BASE_DEC, NULL, 0x0,
3323
16
        NULL, HFILL }
3324
16
    },
3325
16
    { &hf_capability_value,
3326
16
      { "Value", "wccp.capability.value", FT_BYTES, BASE_NONE, NULL, 0x0,
3327
16
        NULL, HFILL }
3328
16
    },
3329
16
    { &hf_reserved_zero,
3330
16
      { "Reserved, must be 0", "wccp.reserved_zero", FT_UINT16, BASE_DEC, NULL, 0x0,
3331
16
        NULL, HFILL }
3332
16
    },
3333
16
    { &hf_value_element_src_ip_index,
3334
16
      { "Source Address", "wccp.value_element.src_ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3335
16
        NULL, HFILL }
3336
16
    },
3337
16
    { &hf_value_element_src_ipv4,
3338
16
      { "Source Address", "wccp.value_element.src_ip.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3339
16
        NULL, HFILL }
3340
16
    },
3341
16
    { &hf_value_element_src_ipv6,
3342
16
      { "Source Address", "wccp.value_element.src_ip.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3343
16
        NULL, HFILL }
3344
16
    },
3345
16
    { &hf_value_element_dest_ip_index,
3346
16
      { "Destination Address", "wccp.value_element.dest_ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3347
16
        NULL, HFILL }
3348
16
    },
3349
16
    { &hf_value_element_dest_ipv4,
3350
16
      { "Destination Address", "wccp.value_element.dest_ip.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3351
16
        NULL, HFILL }
3352
16
    },
3353
16
    { &hf_value_element_dest_ipv6,
3354
16
      { "Destination Address", "wccp.value_element.dest_ip.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3355
16
        NULL, HFILL }
3356
16
    },
3357
16
    { &hf_value_element_src_port,
3358
16
      { "Source Port", "wccp.value_element.src_port", FT_UINT16, BASE_DEC, NULL, 0x0,
3359
16
        NULL, HFILL }
3360
16
    },
3361
16
    { &hf_value_element_dest_port,
3362
16
      { "Destination Port", "wccp.value_element.dest_port", FT_UINT16, BASE_DEC, NULL, 0x0,
3363
16
        NULL, HFILL }
3364
16
    },
3365
16
    { &hf_value_element_web_cache_ip_index,
3366
16
      { "Web Cache Address", "wccp.value_element.web_cache_ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3367
16
        NULL, HFILL }
3368
16
    },
3369
16
    { &hf_value_element_web_cache_ipv4,
3370
16
      { "Web Cache Address", "wccp.value_element.web_cache_ip.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3371
16
        NULL, HFILL }
3372
16
    },
3373
16
    { &hf_value_element_web_cache_ipv6,
3374
16
      { "Web Cache Address", "wccp.value_element.web_cache_ip.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3375
16
        NULL, HFILL }
3376
16
    },
3377
16
    { &hf_mask_value_set_list_num_elements,
3378
16
      { "Number of elements", "wccp.mask_value_set_list.num_elements", FT_UINT32, BASE_DEC, NULL, 0x0,
3379
16
        NULL, HFILL }
3380
16
    },
3381
16
    { &hf_mask_element_src_ip,
3382
16
      { "Source Address Mask", "wccp.mask_element.src_ip", FT_UINT32, BASE_HEX, NULL, 0x0,
3383
16
        NULL, HFILL }
3384
16
    },
3385
16
    { &hf_mask_element_dest_ip,
3386
16
      { "Destination Address Mask", "wccp.mask_element.dest_ip", FT_UINT32, BASE_HEX, NULL, 0x0,
3387
16
        NULL, HFILL }
3388
16
    },
3389
16
    { &hf_mask_element_src_port,
3390
16
      { "Source Port Mask", "wccp.mask_element.src_port", FT_UINT16, BASE_HEX, NULL, 0x0,
3391
16
        NULL, HFILL }
3392
16
    },
3393
16
    { &hf_mask_element_dest_port,
3394
16
      { "Destination Port Mask", "wccp.mask_element.dest_port", FT_UINT16, BASE_HEX, NULL, 0x0,
3395
16
        NULL, HFILL }
3396
16
    },
3397
16
    { &hf_alt_assignment_info_assignment_type,
3398
16
      { "Assignment type", "wccp.alt_assignment_info.assignment_type", FT_UINT16, BASE_DEC, VALS(assignment_type_vals), 0x0,
3399
16
        NULL, HFILL }
3400
16
    },
3401
16
    { &hf_extended_assignment_data_type,
3402
16
      { "Assignment type", "wccp.extended_assignment_data.type", FT_UINT16, BASE_DEC, VALS(assignment_type_vals), 0x0,
3403
16
        NULL, HFILL }
3404
16
    },
3405
16
    { &hf_alt_assignment_map_assignment_type,
3406
16
      { "Assignment type", "wccp.alt_assignment_map.assignment_type", FT_UINT16, BASE_DEC, VALS(assignment_type_vals), 0x0,
3407
16
        NULL, HFILL }
3408
16
    },
3409
16
    { &hf_alt_assignment_map_assignment_length,
3410
16
      { "Assignment length", "wccp.alt_assignment_map.assignment_length", FT_UINT16, BASE_DEC, NULL, 0x0,
3411
16
        NULL, HFILL }
3412
16
    },
3413
16
    { &hf_alt_assignment_info_assignment_length,
3414
16
      { "Assignment length", "wccp.alt_assignment_info.assignment_length", FT_UINT16, BASE_DEC, NULL, 0x0,
3415
16
        NULL, HFILL }
3416
16
    },
3417
16
    { &hf_extended_assignment_data_length,
3418
16
      { "Assignment length", "wccp.extended_assignment_data.length", FT_UINT16, BASE_DEC, NULL, 0x0,
3419
16
        NULL, HFILL }
3420
16
    },
3421
16
    { &hf_alt_assignment_info_num_routers,
3422
16
      { "Number of routers", "wccp.alt_assignment_info.num_routers", FT_UINT32, BASE_DEC, NULL, 0x0,
3423
16
        NULL, HFILL }
3424
16
    },
3425
16
    { &hf_alt_assignment_mask_value_set_element_num_wc_value_elements,
3426
16
      { "Number of Web-Cache Value Elements", "wccp.alt_assignment_mask_value_set_element.num_wc_value_elements", FT_UINT32, BASE_DEC, NULL, 0x0,
3427
16
        NULL, HFILL }
3428
16
    },
3429
16
    { &hf_web_cache_value_element_wc_address_index,
3430
16
      { "Web-Cache Address", "wccp.web_cache_value_element.wc_address.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3431
16
        NULL, HFILL }
3432
16
    },
3433
16
    { &hf_web_cache_value_element_wc_address_ipv4,
3434
16
      { "Web-Cache Address", "wccp.web_cache_value_element.wc_address.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3435
16
        NULL, HFILL }
3436
16
    },
3437
16
    { &hf_web_cache_value_element_wc_address_ipv6,
3438
16
      { "Web-Cache Address", "wccp.web_cache_value_element.wc_address.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3439
16
        NULL, HFILL }
3440
16
    },
3441
16
    { &hf_web_cache_value_element_num_values,
3442
16
      { "Number of Value Sequence Numbers", "wccp.web_cache_value_element.num_values", FT_UINT32, BASE_DEC, NULL, 0x0,
3443
16
        NULL, HFILL }
3444
16
    },
3445
16
    { &hf_web_cache_value_seq_num,
3446
16
      { "Value Sequence Number", "wccp.web_cache_value_element.value_seq_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3447
16
        NULL, HFILL }
3448
16
    },
3449
16
    { &hf_alt_assignment_mask_value_set_list_num_elements,
3450
16
      { "Number of Alternate Mask/Value Set Elements", "wccp.alt_assignment_mask_value_list.num_elements", FT_UINT32, BASE_DEC, NULL, 0x0,
3451
16
        NULL, HFILL }
3452
16
    },
3453
16
    { &hf_address_table_family,
3454
16
      { "Family Type", "wccp.address_table.family_type", FT_UINT16, BASE_DEC, VALS(wccp_address_family_val), 0x0,
3455
16
        "The WCCP Address Table Family type", HFILL }
3456
16
    },
3457
16
    { &hf_address_table_address_length,
3458
16
      { "Address Length", "wccp.address_table.address_length", FT_UINT16, BASE_DEC, NULL, 0x0,
3459
16
        "The WCCP Address Table Address Length", HFILL }
3460
16
    },
3461
16
    { &hf_address_table_length,
3462
16
      { "Length", "wccp.address_table.length", FT_UINT32, BASE_DEC, NULL, 0x0,
3463
16
        "The WCCP Address Table Length", HFILL }
3464
16
    },
3465
16
    { &hf_address_table_element,
3466
16
      { "Address", "wccp.address_table.element", FT_STRING, BASE_NONE, NULL, 0x0,
3467
16
        NULL, HFILL }
3468
16
    },
3469
3470
16
  };
3471
16
  static int *ett[] = {
3472
16
    &ett_wccp,
3473
16
    &ett_buckets,
3474
16
    &ett_hash_assignment_buckets,
3475
16
    &ett_mask_assignment_data_element,
3476
16
    &ett_alternate_mask_assignment_data_element,
3477
16
    &ett_extended_assigment_data_element,
3478
16
    &ett_table_element,
3479
16
    &ett_hash_flags,
3480
16
    &ett_wc_identity_flags,
3481
16
    &ett_cache_info,
3482
16
    &ett_security_info,
3483
16
    &ett_service_info,
3484
16
    &ett_service_flags,
3485
16
    &ett_service_info_ports,
3486
16
    &ett_wc_view_info_router_element,
3487
16
    &ett_router_identity_info,
3488
16
    &ett_wc_identity_element,
3489
16
    &ett_wc_identity_info,
3490
16
    &ett_router_view_info,
3491
16
    &ett_wc_view_info,
3492
16
    &ett_router_assignment_element,
3493
16
    &ett_hash_buckets_assignment_wc_element,
3494
16
    &ett_hash_buckets_assignment_buckets,
3495
16
    &ett_router_alt_assignment_element,
3496
16
    &ett_router_assignment_info,
3497
16
    &ett_query_info,
3498
16
    &ett_capabilities_info,
3499
16
    &ett_capability_element,
3500
16
    &ett_capability_forwarding_method,
3501
16
    &ett_capability_assignment_method,
3502
16
    &ett_capability_return_method,
3503
16
    &ett_capability_transmit_t,
3504
16
    &ett_capability_timer_scale,
3505
16
    &ett_alt_assignment_info,
3506
16
    &ett_alt_assignment_map,
3507
16
    &ett_address_table,
3508
16
    &ett_assignment_map,
3509
16
    &ett_command_extension,
3510
16
    &ett_alternate_mask_value_set,
3511
16
    &ett_alternate_mask_value_set_element,
3512
16
    &ett_mv_set_list,
3513
16
    &ett_mv_set_element,
3514
16
    &ett_mv_set_value_list,
3515
16
    &ett_alternate_mv_set_element_list,
3516
16
    &ett_web_cache_value_element_list,
3517
16
    &ett_alternate_mv_set_element,
3518
16
    &ett_value_element,
3519
16
    &ett_unknown_info,
3520
16
  };
3521
3522
16
  static ei_register_info ei[] = {
3523
16
     { &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 }},
3524
16
     { &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 }},
3525
16
     { &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 }},
3526
16
     { &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 }},
3527
16
     { &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 }},
3528
16
     { &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 }},
3529
16
     { &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 }},
3530
16
     { &ei_wccp_missing_assignment, { "wccp.missing.assignment", PI_PROTOCOL, PI_ERROR, "This message should contain a Alternate Assignment, Assignment Map, Assignment Info or "
3531
16
                                      "Alternative Assignment Map component, but it is missing", EXPFILL }},
3532
16
     { &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 }},
3533
16
     { &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 }},
3534
16
     { &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 }},
3535
16
     { &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 }},
3536
16
     { &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 }},
3537
16
     { &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 }},
3538
16
     { &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 }},
3539
16
     { &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 }},
3540
16
     { &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 }},
3541
16
     { &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 }},
3542
16
     { &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 }},
3543
16
     { &ei_wccp_assignment_length_bad, { "wccp.assignment_length_bad", PI_PROTOCOL, PI_ERROR, "Assignment length bad", EXPFILL }},
3544
16
     { &ei_wccp_length_bad, { "wccp.length_bad", PI_PROTOCOL, PI_ERROR, "Length bad", EXPFILL }},
3545
16
     { &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 }},
3546
16
     { &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 }},
3547
16
     { &ei_wccp_router_identity_receive_id_zero, { "wccp.router_identity.receive_id.zero", PI_PROTOCOL, PI_WARN, "Receive ID shouldn't be 0", EXPFILL }},
3548
16
     { &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 }},
3549
16
     { &ei_wccp_address_table_family_unknown, { "wccp.address_table.family_type.unknown", PI_PROTOCOL, PI_ERROR, "Unknown address family", EXPFILL }},
3550
16
     { &ei_wccp_capability_element_length, { "wccp.capability_element.length.invalid", PI_PROTOCOL, PI_WARN, "Value Length invalid", EXPFILL }},
3551
16
     { &ei_wccp_port_fields_not_used, { "wccp.port_fields_not_used", PI_PROTOCOL, PI_NOTE, "Ports fields not used", EXPFILL }},
3552
16
     { &ei_wccp_a_zero_not_c, { "wccp.a_zero_not_c", PI_PROTOCOL, PI_WARN, "Error A is 0, but C is not", EXPFILL }},
3553
#if 0
3554
     { &ei_wccp_c_zero_not_a, { "wccp.c_zero_not_a", PI_PROTOCOL, PI_WARN, "Error C is 0, but A is not", EXPFILL }},
3555
#endif
3556
16
  };
3557
3558
16
  expert_module_t* expert_wccp;
3559
3560
16
  proto_wccp = proto_register_protocol("Web Cache Communication Protocol",
3561
16
                                       "WCCP", "wccp");
3562
16
  proto_register_field_array(proto_wccp, hf, array_length(hf));
3563
16
  proto_register_subtree_array(ett, array_length(ett));
3564
16
  expert_wccp = expert_register_protocol(proto_wccp);
3565
16
  expert_register_field_array(expert_wccp, ei, array_length(ei));
3566
16
  wccp_handle = register_dissector("wccp", dissect_wccp, proto_wccp);
3567
16
}
3568
3569
void
3570
proto_reg_handoff_wccp(void)
3571
16
{
3572
16
  dissector_add_uint_with_preference("udp.port", UDP_PORT_WCCP, wccp_handle);
3573
16
}
3574
3575
/*
3576
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
3577
 *
3578
 * Local variables:
3579
 * c-basic-offset: 2
3580
 * tab-width: 8
3581
 * indent-tabs-mode: nil
3582
 * End:
3583
 *
3584
 * vi: set shiftwidth=2 tabstop=8 expandtab:
3585
 * :indentSize=2:tabSize=8:noTabs=true:
3586
 */