Coverage Report

Created: 2026-07-12 07:10

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