Coverage Report

Created: 2026-08-14 06:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-wccp.c
Line
Count
Source
1
/* packet-wccp.c
2
 * Routines for Web Cache C* Protocol dissection
3
 * Jerry Talkington <jtalkington@users.sourceforge.net>
4
 *
5
 * https://datatracker.ietf.org/doc/html/draft-mclaggan-wccp-v2rev1-00
6
 *
7
 * Wireshark - Network traffic analyzer
8
 * By Gerald Combs <gerald@wireshark.org>
9
 * Copyright 1998 Gerald Combs
10
 *
11
 * SPDX-License-Identifier: GPL-2.0-or-later
12
 */
13
14
#include "config.h"
15
16
#include <epan/packet.h>
17
#include <epan/to_str.h>
18
#include <epan/expert.h>
19
#include <epan/tfs.h>
20
#include <epan/iana-info.h>
21
#include <wsutil/array.h>
22
#include <wsutil/ws_roundup.h>
23
#include "packet-wccp.h"
24
25
void proto_register_wccp(void);
26
void proto_reg_handoff_wccp(void);
27
28
static dissector_handle_t wccp_handle;
29
30
static int proto_wccp;
31
static int hf_wccp_message_type;   /* the message type */
32
static int hf_wccp_version;        /* protocol version */
33
static int hf_bucket;
34
static int hf_bucket_bit;
35
static int hf_message_header_version;
36
static int hf_hash_revision;       /* the version of the hash */
37
static int hf_change_num;          /* change number */
38
static int hf_hash_flag;
39
static int hf_hash_flag_u;
40
static int hf_recvd_id;
41
static int hf_wc_num;
42
static int hf_wc_view_wc_num;
43
static int hf_cache_ip;
44
static int hf_message_header_length;
45
static int hf_item_type;
46
static int hf_item_length;
47
static int hf_item_data;
48
static int hf_security_info_option;
49
static int hf_security_info_md5_checksum;
50
static int hf_command_element_type;
51
static int hf_command_element_length;
52
static int hf_command_length;
53
static int hf_command_element_shutdown_ip_index;
54
static int hf_command_element_shutdown_ipv4;
55
static int hf_command_element_shutdown_ipv6;
56
static int hf_command_unknown;
57
static int hf_service_info_type;
58
static int hf_service_info_id_standard;
59
static int hf_service_info_id_dynamic;
60
static int hf_service_info_priority;
61
static int hf_service_info_protocol;
62
static int hf_service_info_flags;
63
static int hf_service_info_flags_src_ip_hash;
64
static int hf_service_info_flags_dest_ip_hash;
65
static int hf_service_info_flags_src_port_hash;
66
static int hf_service_info_flags_dest_port_hash;
67
static int hf_service_info_flags_ports_defined;
68
static int hf_service_info_flags_ports_source;
69
static int hf_service_info_flags_redirect_only_protocol_0;
70
static int hf_service_info_flags_src_ip_alt_hash;
71
static int hf_service_info_flags_dest_ip_alt_hash;
72
static int hf_service_info_flags_src_port_alt_hash;
73
static int hf_service_info_flags_dest_port_alt_hash;
74
static int hf_service_info_flags_reserved;
75
static int hf_service_info_source_port;
76
static int hf_service_info_destination_port;
77
static int hf_router_identity_ip_index;
78
static int hf_router_identity_ipv4;
79
static int hf_router_identity_ipv6;
80
static int hf_router_identity_receive_id;
81
static int hf_router_identity_send_to_ip_index;
82
static int hf_router_identity_send_to_ipv4;
83
static int hf_router_identity_send_to_ipv6;
84
static int hf_router_identity_received_from_num;
85
static int hf_web_cache_identity_index;
86
static int hf_web_cache_identity_ipv4;
87
static int hf_web_cache_identity_ipv6;
88
static int hf_web_cache_identity_hash_rev;
89
static int hf_web_cache_identity_flags;
90
static int hf_web_cache_identity_flag_hash_info;
91
static int hf_web_cache_identity_flag_assign_type;
92
static int hf_web_cache_identity_flag_version_request;
93
static int hf_web_cache_identity_flag_reserved;
94
static int hf_mask_value_set_element_value_element_num;
95
static int hf_assignment_weight;
96
static int hf_assignment_status;
97
static int hf_assignment_key_ip_index;
98
static int hf_assignment_key_ipv4;
99
static int hf_assignment_key_ipv6;
100
static int hf_assignment_key_change_num;
101
static int hf_assignment_no_data;
102
static int hf_router_view_member_change_num;
103
static int hf_router_router_num;
104
static int hf_router_identity_router_ip_index;
105
static int hf_router_identity_router_ipv4;
106
static int hf_router_identity_router_ipv6;
107
static int hf_wc_view_info_change_num;
108
static int hf_wc_view_info_router_ip_index;
109
static int hf_wc_view_info_router_ipv4;
110
static int hf_wc_view_info_router_ipv6;
111
static int hf_wc_view_info_wc_ip_index;
112
static int hf_wc_view_info_wc_ipv4;
113
static int hf_wc_view_info_wc_ipv6;
114
static int hf_wc_view_router_num;
115
static int hf_wc_identity_ip_address_index;
116
static int hf_wc_identity_ip_address_ipv4;
117
static int hf_wc_identity_ip_address_ipv6;
118
static int hf_router_identity_received_from_ip_index;
119
static int hf_router_identity_received_from_ipv4;
120
static int hf_router_identity_received_from_ipv6;
121
static int hf_router_assignment_element_change_num;
122
static int hf_assignment_info_router_num;
123
static int hf_hash_buckets_assignment_wc_num;
124
static int hf_hash_buckets_assignment_wc_ip_index;
125
static int hf_hash_buckets_assignment_wc_ipv4;
126
static int hf_hash_buckets_assignment_wc_ipv6;
127
static int hf_assignment_info_router_ip_index;
128
static int hf_assignment_info_router_ipv4;
129
static int hf_assignment_info_router_ipv6;
130
static int hf_router_view_ip_index;
131
static int hf_router_view_ipv4;
132
static int hf_router_view_ipv6;
133
static int hf_router_query_info_ip_index;
134
static int hf_router_query_info_ipv4;
135
static int hf_router_query_info_ipv6;
136
static int hf_router_query_info_send_to_ip_index;
137
static int hf_router_query_info_send_to_ipv4;
138
static int hf_router_query_info_send_to_ipv6;
139
static int hf_router_query_info_target_ip_index;
140
static int hf_router_query_info_target_ipv4;
141
static int hf_router_query_info_target_ipv6;
142
static int hf_capability_element_type;
143
static int hf_capability_element_length;
144
static int hf_capability_info_value;
145
static int hf_capability_forwarding_method_flag_gre;
146
static int hf_capability_forwarding_method_flag_l2;
147
static int hf_capability_assignment_method_flag_hash;
148
static int hf_capability_assignment_method_flag_mask;
149
static int hf_capability_return_method_flag_gre;
150
static int hf_capability_return_method_flag_l2;
151
static int hf_capability_transmit_t;
152
static int hf_capability_transmit_t_upper_limit;
153
static int hf_capability_transmit_t_lower_limit;
154
static int hf_capability_timer_scale_timeout_scale;
155
static int hf_capability_timer_scale_ra_timer_scale;
156
static int hf_capability_timer_scale_timeout_scale_upper_limit;
157
static int hf_capability_timer_scale_timeout_scale_lower_limit;
158
static int hf_capability_timer_scale_ra_scale_upper_limit;
159
static int hf_capability_timer_scale_ra_scale_lower_limit;
160
static int hf_capability_value;
161
static int hf_reserved_zero;
162
static int hf_value_element_src_ip_index;
163
static int hf_value_element_src_ipv4;
164
static int hf_value_element_src_ipv6;
165
static int hf_value_element_dest_ip_index;
166
static int hf_value_element_dest_ipv4;
167
static int hf_value_element_dest_ipv6;
168
static int hf_value_element_src_port;
169
static int hf_value_element_dest_port;
170
static int hf_value_element_web_cache_ip_index;
171
static int hf_value_element_web_cache_ipv4;
172
static int hf_value_element_web_cache_ipv6;
173
static int hf_mask_value_set_list_num_elements;
174
static int hf_mask_element_src_ip;
175
static int hf_mask_element_dest_ip;
176
static int hf_mask_element_src_port;
177
static int hf_mask_element_dest_port;
178
static int hf_alt_assignment_info_assignment_type;
179
static int hf_extended_assignment_data_type;
180
static int hf_alt_assignment_info_assignment_length;
181
static int hf_alt_assignment_map_assignment_type;
182
static int hf_alt_assignment_map_assignment_length;
183
static int hf_extended_assignment_data_length;
184
static int hf_alt_assignment_info_num_routers;
185
static int hf_alt_assignment_mask_value_set_element_num_wc_value_elements;
186
static int hf_web_cache_value_element_wc_address_index;
187
static int hf_web_cache_value_element_wc_address_ipv4;
188
static int hf_web_cache_value_element_wc_address_ipv6;
189
static int hf_web_cache_value_element_num_values;
190
static int hf_web_cache_value_seq_num;
191
static int hf_alt_assignment_mask_value_set_list_num_elements;
192
static int hf_address_table_family;
193
static int hf_address_table_address_length;
194
static int hf_address_table_length;
195
static int hf_address_table_element;
196
197
static int ett_wccp;
198
static int ett_buckets;
199
static int ett_hash_assignment_buckets;
200
static int ett_mask_assignment_data_element;
201
static int ett_alternate_mask_assignment_data_element;
202
static int ett_extended_assigment_data_element;
203
static int ett_table_element;
204
static int ett_hash_flags;
205
static int ett_wc_identity_flags;
206
static int ett_cache_info;
207
static int ett_security_info;
208
static int ett_service_info;
209
static int ett_service_flags;
210
static int ett_service_info_ports;
211
static int ett_wc_view_info_router_element;
212
static int ett_router_identity_info;
213
static int ett_wc_identity_element;
214
static int ett_wc_identity_info;
215
static int ett_router_view_info;
216
static int ett_wc_view_info;
217
static int ett_router_assignment_element;
218
static int ett_hash_buckets_assignment_wc_element;
219
static int ett_hash_buckets_assignment_buckets;
220
static int ett_router_alt_assignment_element;
221
static int ett_router_assignment_info;
222
static int ett_query_info;
223
static int ett_capabilities_info;
224
static int ett_capability_element;
225
static int ett_capability_forwarding_method;
226
static int ett_capability_assignment_method;
227
static int ett_capability_return_method;
228
static int ett_capability_transmit_t;
229
static int ett_capability_timer_scale;
230
static int ett_alt_assignment_info;
231
static int ett_alt_assignment_map;
232
static int ett_address_table;
233
static int ett_assignment_map;
234
static int ett_command_extension;
235
static int ett_alternate_mask_value_set;
236
static int ett_alternate_mask_value_set_element;
237
static int ett_mv_set_list;
238
static int ett_mv_set_element;
239
static int ett_mv_set_value_list;
240
static int ett_alternate_mv_set_element_list;
241
static int ett_web_cache_value_element_list;
242
static int ett_alternate_mv_set_element;
243
static int ett_value_element;
244
static int ett_unknown_info;
245
246
static expert_field ei_wccp_missing_security_info;
247
static expert_field ei_wccp_missing_service_info;
248
static expert_field ei_wccp_missing_wc_id_info;
249
static expert_field ei_wccp_missing_router_id_info;
250
static expert_field ei_wccp_missing_query_info;
251
static expert_field ei_wccp_missing_wc_view_info;
252
static expert_field ei_wccp_missing_rtr_view_info;
253
static expert_field ei_wccp_contains_redirect_assignment;
254
static expert_field ei_wccp_contains_router_id_info;
255
static expert_field ei_wccp_contains_rtr_view_info;
256
static expert_field ei_wccp_contains_query_info;
257
static expert_field ei_wccp_contains_alt_assignment;
258
static expert_field ei_wccp_contains_assign_map;
259
static expert_field ei_wccp_contains_alt_assignment_map;
260
static expert_field ei_wccp_contains_wc_id_info;
261
static expert_field ei_wccp_contains_wc_view_info;
262
static expert_field ei_wccp_contains_capabilities_info;
263
static expert_field ei_wccp_contains_command_extension;
264
static expert_field ei_wccp_missing_assignment;
265
static expert_field ei_wccp_assignment_length_bad;
266
static expert_field ei_wccp_length_bad;
267
static expert_field ei_wccp_service_info_priority_nonzero;
268
static expert_field ei_wccp_service_info_protocol_nonzero;
269
static expert_field ei_wccp_router_identity_receive_id_zero;
270
static expert_field ei_wccp_web_cache_identity_hash_rev_zero;
271
static expert_field ei_wccp_address_table_family_unknown;
272
static expert_field ei_wccp_capability_element_length;
273
static expert_field ei_wccp_port_fields_not_used;
274
static expert_field ei_wccp_a_zero_not_c;
275
/* static expert_field ei_wccp_c_zero_not_a; */
276
277
/*
278
 * At
279
 *
280
 *      https://datatracker.ietf.org/doc/html/draft-forster-wrec-wccp-v1-00
281
 *
282
 * is the now-expired Internet-Draft for WCCP 1.0 (Web Cache Coordination
283
 * Protocol V1.0).
284
 *
285
 * At
286
 *
287
 *      https://datatracker.ietf.org/doc/html/draft-wilson-wrec-wccp-v2-01
288
 *
289
 * is the now-expired Internet-Draft for WCCP 2.0 (Web Cache Communication
290
 * Protocol V2.0).
291
 *
292
 *      https://datatracker.ietf.org/doc/html/draft-param-wccp-v2rev1-01
293
 *
294
 * is the now-expired Internet-Draft for WCCP 2.01 (Web Cache Communication
295
 * Protocol V2, Revision 1).
296
 */
297
298
/* This is NOT IANA assigned */
299
16
#define UDP_PORT_WCCP           2048
300
301
#define WCCPv1                  4
302
#define WCCPv2                  0x0200
303
#define WCCPv2r1                0x0201
304
1
#define WCCP_HERE_I_AM          7
305
18
#define WCCP_I_SEE_YOU          8
306
23
#define WCCP_ASSIGN_BUCKET      9
307
29
#define WCCP2_HERE_I_AM         10
308
32
#define WCCP2_I_SEE_YOU         11
309
432
#define WCCP2_REDIRECT_ASSIGN   12
310
42
#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
64
#define WCCP2_HASH_ASSIGNMENT_TYPE         0
344
8
#define WCCP2_MASK_ASSIGNMENT_TYPE         1
345
37
#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
67
#define HASH_INFO_SIZE          (4*(1+8+1))
357
358
483
#define WCCP2_SECURITY_INFO             0
359
8
#define WCCP2_SERVICE_INFO              1
360
19
#define WCCP2_ROUTER_ID_INFO            2
361
6
#define WCCP2_WC_ID_INFO                3
362
74
#define WCCP2_RTR_VIEW_INFO             4
363
27
#define WCCP2_WC_VIEW_INFO              5
364
38
#define WCCP2_REDIRECT_ASSIGNMENT       6
365
6
#define WCCP2_QUERY_INFO                7
366
12
#define WCCP2_CAPABILITIES_INFO         8
367
64
#define WCCP2_ALT_ASSIGNMENT            13
368
36
#define WCCP2_ASSIGN_MAP                14
369
22
#define WCCP2_COMMAND_EXTENSION         15
370
/* WCCP 2 r1 additions: */
371
66
#define WCCP2r1_ALT_ASSIGNMENT_MAP      16
372
753
#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
178
#define WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_HASH        0
407
20
#define WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_MASK        1
408
115
#define WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_NOT_PRESENT 2
409
214
#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
2
#define WCCP2_FORWARDING_METHOD         0x01
420
1
#define WCCP2_ASSIGNMENT_METHOD         0x02
421
0
#define WCCP2_PACKET_RETURN_METHOD      0x03
422
1
#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
374
{
503
374
  uint16_t type;
504
374
  uint16_t item_length;
505
506
1.01k
  for (;;) {
507
1.01k
    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
13
      return;
511
13
    }
512
1.00k
    type = tvb_get_ntohs(tvb, offset);
513
1.00k
    item_length = tvb_get_ntohs(tvb, offset+2);
514
515
1.00k
    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
298
      return;
519
298
    }
520
521
707
    if (type == WCCP2r1_ADDRESS_TABLE)
522
63
      {
523
63
        dissect_wccp2r1_address_table_info(tvb, offset+4, item_length, pinfo, NULL, wccp_wccp_address_table);
524
        /* no need to decode the rest */
525
63
        return;
526
63
      }
527
528
644
    offset = offset + (item_length + 4);
529
644
  }
530
374
}
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
991
{
552
991
  uint32_t host_addr;
553
991
  char *buffer;
554
555
  /* are we using an address table? */
556
991
  if (!addr_table->in_use)
557
572
    {
558
      /* no; return the IPv4 IP */
559
572
      host_addr = tvb_get_ipv4(tvb,offset);
560
572
      buffer = (char *) wmem_alloc(pinfo->pool, WS_INET_ADDRSTRLEN);
561
572
      ip_addr_to_str_buf(&host_addr, buffer, WS_INET_ADDRSTRLEN);
562
572
    }
563
419
  else
564
419
    {
565
      /* yes; we need to decode the encoded address */
566
419
      uint16_t reserv;
567
419
      uint16_t addr_index;
568
569
419
      host_addr = tvb_get_ntohl(tvb,offset);
570
419
      reserv = (host_addr & 0xFFFF0000) >> 16;
571
419
      addr_index = (host_addr & 0x0000FFFF);
572
573
419
      if (reserv != 0) {
574
307
        buffer = wmem_strdup(pinfo->pool, "INVALID: reserved part non zero");
575
307
      }
576
112
      else {
577
        /* now check if it's IPv4 or IPv6 we need to print */
578
112
        switch (addr_table->family) {
579
67
        case 1:
580
          /* IPv4 */
581
582
          /* special case: index 0 -> undefined IP */
583
67
          if (addr_index == 0) {
584
38
            buffer = wmem_strdup(pinfo->pool, "0.0.0.0");
585
38
            break;
586
38
          }
587
          /* are we be beyond the end of the table? */
588
29
          if (addr_index > addr_table->table_length) {
589
29
            buffer = wmem_strdup_printf(pinfo->pool, "INVALID IPv4 index: %d > %d",
590
29
                       addr_index, addr_table->table_length);
591
29
            break;
592
29
          }
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
18
        default:
628
18
          buffer = wmem_strdup(pinfo->pool, "INVALID IP family");
629
18
          break;
630
112
        }
631
112
      }
632
419
    }
633
634
964
  return buffer;
635
991
}
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
5.42k
{
640
5.42k
    uint32_t host_addr;
641
5.42k
    ws_in6_addr ipv6_zero;
642
5.42k
    uint16_t reserv, addr_index;
643
644
    /* are we using an address table? */
645
5.42k
    if (! addr_table->in_use)
646
3.96k
      return proto_tree_add_item(tree, hf_ipv4, tvb, offset, length, ENC_BIG_ENDIAN);
647
648
1.45k
    host_addr = tvb_get_ntohl(tvb, offset);
649
650
    /* we need to decode the encoded address: */
651
1.45k
    reserv = (host_addr & 0xFFFF0000) >> 16;
652
1.45k
    addr_index  = (host_addr & 0x0000FFFF);
653
654
1.45k
    memset(&ipv6_zero, 0, sizeof(ipv6_zero));
655
656
1.45k
    if (reserv != 0)
657
1.13k
      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
318
    switch (addr_table->family) {
661
200
    case 1:
662
    /* IPv4 */
663
664
        /* special case: index 0 -> undefined IP */
665
200
        if (addr_index == 0) {
666
121
          return proto_tree_add_item(tree, hf_ipv4, tvb, offset, length, ENC_LITTLE_ENDIAN);
667
121
        }
668
        /* are we be beyond the end of the table? */
669
79
        if (addr_index > addr_table->table_length) {
670
79
          return proto_tree_add_uint_format_value(tree, hf_index, tvb, offset, length, host_addr,
671
79
                     "INVALID IPv4 index: %d > %d", addr_index, addr_table->table_length);
672
79
        }
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
318
    }
702
703
117
    return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, host_addr, "INVALID IP family");
704
318
}
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
66
{
712
66
  proto_tree *bucket_tree;
713
66
  proto_item *tf;
714
66
  proto_tree *field_tree;
715
66
  int i;
716
66
  uint8_t bucket_info;
717
66
  int n;
718
719
66
  proto_tree_add_item(wccp_tree, hf_hash_revision, tvb, offset, 4,
720
66
                      ENC_BIG_ENDIAN);
721
66
  offset += 4;
722
723
66
  bucket_tree = proto_tree_add_subtree(wccp_tree, tvb, offset, 32,
724
66
                                    ett_buckets, NULL, "Hash information");
725
726
1.79k
  for (i = 0, n = 0; i < 32; i++) {
727
1.72k
    bucket_info = tvb_get_uint8(tvb, offset);
728
1.72k
    n = wccp_bucket_info(bucket_info, bucket_tree, n, tvb, offset);
729
1.72k
    offset += 1;
730
1.72k
  }
731
66
  tf = proto_tree_add_item(wccp_tree, hf_hash_flag, tvb, offset, 4, ENC_BIG_ENDIAN);
732
66
  field_tree = proto_item_add_subtree(tf, ett_hash_flags);
733
66
  proto_tree_add_item(field_tree, hf_hash_flag_u, tvb, offset, 4, ENC_BIG_ENDIAN);
734
66
  offset += 4;
735
66
  return offset;
736
66
}
737
738
static unsigned
739
dissect_web_cache_list_entry(tvbuff_t *tvb, int offset, int idx,
740
                             proto_tree *wccp_tree)
741
67
{
742
67
  proto_tree *list_entry_tree;
743
744
67
  list_entry_tree = proto_tree_add_subtree_format(wccp_tree, tvb, offset, 4 + HASH_INFO_SIZE,
745
67
                           ett_cache_info, NULL, "Web-Cache List Entry(%d)", idx);
746
67
  proto_tree_add_item(list_entry_tree, hf_cache_ip, tvb, offset, 4,
747
67
                      ENC_BIG_ENDIAN);
748
67
  offset += 4;
749
67
  offset = dissect_hash_data(tvb, offset, list_entry_tree);
750
67
  return offset;
751
67
}
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
6.91k
{
762
6.91k
  uint32_t i;
763
764
62.2k
  for(i = 0; i < 8; i++) {
765
55.3k
    proto_tree_add_uint_format(bucket_tree, hf_bucket_bit, tvb, offset, 1, bucket_info & 1<<i,
766
55.3k
                    "Bucket %3d: %s", start, (bucket_info & 1<<i ? "Assigned" : "Not Assigned") );
767
55.3k
    start++;
768
55.3k
  }
769
6.91k
  return start;
770
6.91k
}
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
14.4k
#define EAT(x) {length -= x; offset += x;}
778
779
5.06k
#define EAT_AND_CHECK(x,next) {length -= x; offset += x; if (length < next) return length - next;}
780
781
1.52k
#define CHECK_LENGTH_ADVANCE_OFFSET(new_length) { \
782
1.52k
  int old_offset = offset; \
783
1.52k
  if (new_length<0) return new_length; \
784
1.52k
  offset += length-new_length; \
785
1.43k
  if (old_offset >= offset) return offset - old_offset; \
786
1.43k
  length = new_length; \
787
1.42k
  }
788
789
790
/* 5.1.1 Security Info Component */
791
792
/* Security options */
793
794
#define WCCP2_NO_SECURITY               0
795
48
#define WCCP2_MD5_SECURITY              1
796
797
914
#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
481
{
810
481
  uint32_t security_option;
811
812
481
  if (length < SECURITY_INFO_LEN)
813
433
    return (length-SECURITY_INFO_LEN);
814
815
48
  security_option = tvb_get_ntohl(tvb, offset);
816
48
  proto_tree_add_item(info_tree, hf_security_info_option, tvb, offset, 4, ENC_BIG_ENDIAN);
817
818
48
  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
47
  return length-4;
826
48
}
827
828
829
/* 5.1.2 Service Info Component */
830
831
16
#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
16
#define WCCP2_SI_SRC_IP_HASH                    0x00000001
846
16
#define WCCP2_SI_DST_IP_HASH                    0x00000002
847
16
#define WCCP2_SI_SRC_PORT_HASH                  0x00000004
848
16
#define WCCP2_SI_DST_PORT_HASH                  0x00000008
849
16
#define WCCP2_SI_PORTS_DEFINED                  0x00000010
850
16
#define WCCP2_SI_PORTS_SOURCE                   0x00000020
851
16
#define WCCP2r1_SI_REDIRECT_ONLY_PROTOCOL_0     0x00000040
852
16
#define WCCP2_SI_SRC_IP_ALT_HASH                0x00000100
853
16
#define WCCP2_SI_DST_IP_ALT_HASH                0x00000200
854
16
#define WCCP2_SI_SRC_PORT_ALT_HASH              0x00000400
855
16
#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
8
{
862
8
  uint8_t service_type;
863
8
  uint32_t flags;
864
8
  proto_item *tf;
865
8
  proto_tree *ports_tree;
866
8
  int i;
867
8
  int max_offset = offset+length;
868
869
8
  static int * const flag_fields[] = {
870
8
    &hf_service_info_flags_src_ip_hash,
871
8
    &hf_service_info_flags_dest_ip_hash,
872
8
    &hf_service_info_flags_src_port_hash,
873
8
    &hf_service_info_flags_dest_port_hash,
874
8
    &hf_service_info_flags_ports_defined,
875
8
    &hf_service_info_flags_ports_source,
876
8
    &hf_service_info_flags_redirect_only_protocol_0,
877
8
    &hf_service_info_flags_src_ip_alt_hash,
878
8
    &hf_service_info_flags_dest_ip_alt_hash,
879
8
    &hf_service_info_flags_src_port_alt_hash,
880
8
    &hf_service_info_flags_dest_port_alt_hash,
881
8
    &hf_service_info_flags_reserved,
882
8
    NULL
883
8
  };
884
885
8
  if (length != SERVICE_INFO_LEN)
886
8
    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
703
{
959
703
  proto_item *tf;
960
961
962
703
  wccp_add_ipaddress_item(tree, hf_router_identity_ip_index, hf_router_identity_ipv4, hf_router_identity_ipv6, tvb, offset, 4, addr_table);
963
703
  tf = proto_tree_add_item(tree, hf_router_identity_receive_id, tvb, offset+4, 4, ENC_BIG_ENDIAN);
964
965
703
  if (tvb_get_ntohl(tvb, offset + 4) == 0)
966
146
    expert_add_info(pinfo, tf, &ei_wccp_router_identity_receive_id_zero);
967
703
}
968
969
4
#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
19
{
976
19
  uint32_t n_received_from;
977
19
  unsigned i;
978
19
  proto_item *te;
979
19
  proto_tree *element_tree;
980
981
19
  if (length < 8)
982
4
    return length -  ROUTER_ID_INFO_MIN_LEN;
983
984
985
15
  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
15
  element_tree = proto_item_add_subtree(te,ett_wc_view_info_router_element);
988
989
15
  dissect_wccp2_router_identity_element(tvb,offset,pinfo,element_tree, addr_table);
990
15
  EAT_AND_CHECK(8,4);
991
992
15
  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
15
  EAT_AND_CHECK(4,4);
994
995
14
  n_received_from = tvb_get_ntohl(tvb, offset);
996
14
  proto_tree_add_item(info_tree, hf_router_identity_received_from_num, tvb, offset, 4, ENC_BIG_ENDIAN);
997
14
  EAT(4);
998
999
301
  for (i = 0; i < n_received_from; i++) {
1000
288
    if (length < 4)
1001
1
      return length-4*(i-n_received_from);
1002
1003
1004
287
    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
287
    EAT(4);
1006
287
  }
1007
1008
13
  return length;
1009
14
}
1010
1011
533
#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
531
{
1018
531
  proto_item *tf;
1019
531
  uint16_t flags;
1020
531
  unsigned data_element_type;
1021
1022
531
  static int * const flag_fields[] = {
1023
531
    &hf_web_cache_identity_flag_hash_info,
1024
531
    &hf_web_cache_identity_flag_assign_type,
1025
531
    &hf_web_cache_identity_flag_version_request,
1026
531
    &hf_web_cache_identity_flag_reserved,
1027
531
    NULL
1028
531
  };
1029
1030
531
  if (length < ROUTER_WC_ID_ELEMENT_MIN_LEN)
1031
2
    return length - ROUTER_WC_ID_ELEMENT_MIN_LEN;
1032
1033
529
  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
529
  EAT_AND_CHECK(4,2);
1035
1036
529
  tf = proto_tree_add_item(info_tree, hf_web_cache_identity_hash_rev, tvb, offset, 2, ENC_BIG_ENDIAN);
1037
529
  if (tvb_get_ntohs(tvb, offset) != 0)
1038
436
    expert_add_info(pinfo, tf, &ei_wccp_web_cache_identity_hash_rev_zero);
1039
1040
529
  EAT_AND_CHECK(2,2);
1041
1042
529
  flags = tvb_get_ntohs(tvb, offset);
1043
529
  data_element_type = (flags & 0x6) >> 1;
1044
529
  proto_tree_add_bitmask(info_tree, tvb, offset, hf_web_cache_identity_flags, ett_wc_identity_flags, flag_fields, ENC_BIG_ENDIAN);
1045
1046
529
  EAT(2);
1047
1048
529
  switch (data_element_type) {
1049
178
  case WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_HASH:
1050
178
    return dissect_wccp2_hash_assignment_data_element(tvb,offset,length,pinfo,info_tree);
1051
20
  case WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_MASK:
1052
20
    return dissect_wccp2_mask_assignment_data_element(tvb,offset,length,pinfo,info_tree, addr_table);
1053
1054
115
  case WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_NOT_PRESENT:
1055
115
    proto_tree_add_item(info_tree, hf_assignment_no_data, tvb, offset, 2, ENC_NA);
1056
115
    return length;
1057
214
  case WCCP2_WEB_CACHE_ASSIGNMENT_DATA_TYPE_EXTENDED:
1058
214
    return dissect_wccp2_extended_assignment_data_element(tvb,offset,length,pinfo,info_tree, addr_table);
1059
529
  }
1060
0
  return length;
1061
529
}
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
6
{
1068
6
  proto_item *te;
1069
6
  proto_tree *element_tree;
1070
1071
6
  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
6
                                tvb, offset, 4, addr_table);
1073
1074
6
  element_tree = proto_item_add_subtree(te, ett_wc_identity_element);
1075
6
  return dissect_wccp2_web_cache_identity_element(tvb, offset,length, pinfo,
1076
6
                                                  element_tree, addr_table);
1077
6
}
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
187
{
1084
187
  if (length < 8)
1085
2
    return length -8;
1086
1087
1088
185
  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
185
  EAT_AND_CHECK(4,4);
1091
185
  proto_tree_add_item(info_tree, hf_assignment_key_change_num, tvb, offset, 4, ENC_BIG_ENDIAN);
1092
185
  EAT(4);
1093
1094
185
  return length;
1095
185
}
1096
1097
1098
82
#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
74
{
1105
74
  uint32_t n_routers;
1106
74
  uint32_t n_web_caches;
1107
74
  unsigned i;
1108
74
  proto_item *te;
1109
74
  proto_tree *element_tree;
1110
74
  int new_length;
1111
1112
74
  if (length < ROUTER_VIEW_INFO_MIN_LEN)
1113
8
    return length - ROUTER_VIEW_INFO_MIN_LEN;
1114
1115
66
  proto_tree_add_item(info_tree, hf_router_view_member_change_num, tvb, offset, 4, ENC_BIG_ENDIAN);
1116
66
  EAT(4);
1117
1118
66
  new_length=dissect_wccp2_assignment_key_element(tvb, offset, length, pinfo, info_tree, addr_table);
1119
132
  CHECK_LENGTH_ADVANCE_OFFSET(new_length);
1120
1121
132
  n_routers = tvb_get_ntohl(tvb, offset);
1122
132
  proto_tree_add_uint(info_tree, hf_router_router_num, tvb, offset, 4, n_routers);
1123
132
  EAT(4);
1124
1125
441
  for (i = 0; i < n_routers; i++) {
1126
378
    if (length < 4)
1127
3
      return length - (n_routers-i)*4 - 4;
1128
1129
375
    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
375
    EAT(4);
1131
375
  }
1132
1133
63
  if (length < 4)
1134
0
    return length - 4;
1135
1136
63
  n_web_caches = tvb_get_ntohl(tvb, offset);
1137
63
  proto_tree_add_uint(info_tree, hf_wc_view_wc_num, tvb, offset, 4, n_web_caches);
1138
63
  EAT(4);
1139
1140
586
  for (i = 0; i < n_web_caches; i++) {
1141
534
    int old_length;
1142
534
    old_length = length;
1143
1144
534
    if (length < 4)
1145
1
      return length - 4*(n_web_caches-i);
1146
1147
533
    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
533
    element_tree = proto_item_add_subtree(te, ett_wc_identity_element);
1150
533
    length = dissect_wccp2_web_cache_identity_element(tvb,
1151
533
                                                      offset, length, pinfo,
1152
533
                                                      element_tree, addr_table);
1153
533
    if (length < 0)
1154
10
      return length;
1155
1156
523
    offset += old_length - length;
1157
523
  }
1158
52
  return length;
1159
63
}
1160
1161
29
#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
24
{
1169
24
  uint32_t n_routers;
1170
24
  uint32_t n_web_caches;
1171
24
  unsigned i;
1172
24
  proto_item *te;
1173
24
  proto_tree *element_tree;
1174
1175
1176
24
  if (length < WC_VIEW_INFO_MIN_LEN)
1177
5
    return length - WC_VIEW_INFO_MIN_LEN;
1178
1179
1180
19
  proto_tree_add_item(info_tree, hf_wc_view_info_change_num, tvb, offset, 4, ENC_BIG_ENDIAN);
1181
19
  EAT_AND_CHECK(4,4);
1182
1183
19
  n_routers = tvb_get_ntohl(tvb, offset);
1184
19
  proto_tree_add_uint(info_tree, hf_wc_view_router_num, tvb, offset, 4, n_routers);
1185
19
  EAT(4);
1186
1187
303
  for (i = 0; i < n_routers; i++) {
1188
287
    if (length < 8)
1189
3
      return length -8 * (n_routers-i) - 4;
1190
1191
284
    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
284
    proto_item_set_len(te, 8);
1194
1195
284
    element_tree = proto_item_add_subtree(te,ett_wc_view_info_router_element);
1196
284
    dissect_wccp2_router_identity_element(tvb, offset, pinfo, element_tree, addr_table);
1197
284
    EAT(8);
1198
284
  }
1199
1200
16
  if (length < 4)
1201
0
    return length - 4;
1202
1203
16
  n_web_caches = tvb_get_ntohl(tvb, offset);
1204
16
  proto_tree_add_uint(info_tree, hf_wc_view_wc_num, tvb, offset, 4, n_web_caches);
1205
16
  EAT(4);
1206
1207
329
  for (i = 0; i < n_web_caches; i++) {
1208
313
    if (length < 4)
1209
0
      return length - 4*(n_web_caches-i);
1210
1211
313
    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
313
    EAT(4);
1213
313
  }
1214
16
  return length;
1215
16
}
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
405
{
1222
405
  dissect_wccp2_router_identity_element(tvb,offset,pinfo,info_tree, addr_table);
1223
405
  EAT(8);
1224
405
  proto_tree_add_item(info_tree, hf_router_assignment_element_change_num, tvb, offset, 4, ENC_BIG_ENDIAN);
1225
405
  EAT(4);
1226
405
}
1227
1228
static const char *
1229
assignment_bucket_name(wmem_allocator_t* allocator, uint8_t bucket)
1230
2.20k
{
1231
2.20k
  const char *cur;
1232
1233
2.20k
  if (bucket == 0xff) {
1234
354
    cur= wmem_strdup(allocator, "Unassigned");
1235
1.85k
  } else {
1236
1.85k
    cur=wmem_strdup_printf(allocator, "%u%s", bucket & 0x7F,
1237
1.85k
                         (bucket & 0x80) ? " (Alt)" : "");
1238
1.85k
  }
1239
2.20k
  return cur;
1240
2.20k
}
1241
1242
80
#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
69
{
1249
69
  uint32_t n_routers;
1250
69
  unsigned i;
1251
69
  proto_item *te;
1252
69
  proto_tree *element_tree;
1253
69
  int new_length;
1254
1255
69
  if (length < ASSIGNMENT_INFO_MIN_LEN)
1256
10
    return length - ASSIGNMENT_INFO_MIN_LEN;
1257
1258
1259
59
  new_length=dissect_wccp2_assignment_key_element(tvb, offset, length, pinfo, info_tree, addr_table);
1260
118
  CHECK_LENGTH_ADVANCE_OFFSET(new_length);
1261
1262
118
  n_routers = tvb_get_ntohl(tvb, offset);
1263
118
  proto_tree_add_uint(info_tree, hf_assignment_info_router_num, tvb, offset, 4, n_routers);
1264
118
  EAT(4);
1265
1266
265
  for (i = 0; i < n_routers; i++) {
1267
210
    if (length < 12)
1268
4
      return length - 12*(n_routers-i)-4-256;
1269
1270
206
    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
206
    element_tree = proto_item_add_subtree(te, ett_router_assignment_element);
1273
206
    dissect_wccp2_router_assignment_element(tvb, offset, length , pinfo,
1274
206
                                            element_tree, addr_table);
1275
206
    EAT(12);
1276
206
  }
1277
1278
55
  new_length = dissect_wccp2_hash_buckets_assignment_element(tvb, offset, length, pinfo, info_tree, addr_table);
1279
55
  CHECK_LENGTH_ADVANCE_OFFSET(new_length);
1280
36
  return length;
1281
38
}
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
36
{
1309
36
  uint32_t i,n_web_caches;
1310
36
  proto_item *te;
1311
36
  proto_tree *element_tree;
1312
36
  uint8_t bucket;
1313
1314
36
  if (length < 4)
1315
0
    return length - 4;
1316
1317
36
  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
36
  EAT(4);
1319
1320
36
  element_tree = proto_item_add_subtree(te,ett_hash_buckets_assignment_wc_element);
1321
329
  for (i = 0; i < n_web_caches; i++) {
1322
307
    proto_item *l_te;
1323
1324
307
    if (length < 4)
1325
14
      return length - 4*(n_web_caches-i)-256;
1326
1327
293
    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
293
    proto_item_append_text(l_te, " id: %d", i);
1330
293
    EAT(4);
1331
293
  }
1332
1333
22
  element_tree = proto_tree_add_subtree(info_tree,tvb, offset, 256, ett_hash_buckets_assignment_buckets, NULL, "Buckets");
1334
1335
1.20k
  for (i = 0; i < 256; i++, offset++, length--) {
1336
1.18k
    if (length < 1)
1337
5
      return length - (256-i);
1338
1.18k
    bucket = tvb_get_uint8(tvb, offset);
1339
1.18k
    proto_tree_add_uint_format(element_tree, hf_bucket, tvb, offset, 1,
1340
1.18k
                        bucket, "Bucket %3d: %10s",
1341
1.18k
                        i, assignment_bucket_name(pinfo->pool, bucket));
1342
1.18k
  }
1343
17
  return length;
1344
22
}
1345
1346
16
#define WCCP2_FORWARDING_METHOD_GRE     0x00000001
1347
16
#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
16
#define WCCP2_ASSIGNMENT_METHOD_HASH    0x00000001
1356
16
#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
16
#define WCCP2_PACKET_RETURN_METHOD_GRE  0x00000001
1366
16
#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
83
#define WCCP2_COMMAND_TYPE_SHUTDOWN           1
1375
81
#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
12
{
1391
12
  int capability_length;
1392
1393
71
  while (length >= 8) {
1394
69
    capability_length = dissect_wccp2_capability_element(tvb,offset,length,pinfo,info_tree);
1395
1396
118
    CHECK_LENGTH_ADVANCE_OFFSET(capability_length);
1397
118
  }
1398
2
  return length;
1399
12
}
1400
1401
1402
89
#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
22
{
1410
22
  uint16_t command_type;
1411
22
  uint32_t command_length;
1412
1413
88
  for (;;) {
1414
88
    if (length == 0)
1415
2
      return length;
1416
1417
86
    if (length < ALT_COMMAND_EXTENSION_MIN_LEN )
1418
3
      return length - ALT_COMMAND_EXTENSION_MIN_LEN ;
1419
1420
83
    command_type = tvb_get_ntohs(tvb, offset);
1421
83
    proto_tree_add_item(info_tree, hf_command_element_type, tvb, offset, 2, ENC_BIG_ENDIAN);
1422
83
    EAT_AND_CHECK(2,2);
1423
1424
83
    proto_tree_add_item_ret_uint(info_tree, hf_command_element_length, tvb, offset, 2, ENC_BIG_ENDIAN, &command_length);
1425
83
    proto_tree_add_item(info_tree, hf_command_length, tvb, offset, 2, ENC_BIG_ENDIAN);
1426
83
    EAT(2);
1427
1428
83
    if (((command_type == WCCP2_COMMAND_TYPE_SHUTDOWN) ||
1429
81
         (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
83
    } else {
1436
83
      if (length < (int)command_length)
1437
15
        return length - command_length;
1438
1439
68
      proto_tree_add_item(info_tree, hf_command_unknown, tvb, offset, command_length, ENC_NA);
1440
68
    }
1441
68
    EAT(command_length);
1442
68
  }
1443
22
}
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
109
{
1454
109
  uint16_t address_length;
1455
109
  uint32_t i;
1456
109
  uint16_t family;
1457
109
  uint32_t table_length;
1458
109
  proto_tree *element_tree;
1459
109
  proto_item *tf;
1460
1461
109
  if (length < 2*4)
1462
10
    return length - 2*4;
1463
1464
99
  proto_tree_add_item_ret_uint16(info_tree, hf_address_table_family, tvb, offset, 2, ENC_BIG_ENDIAN, &family);
1465
99
  EAT_AND_CHECK(2,2);
1466
1467
99
  proto_tree_add_item_ret_uint16(info_tree, hf_address_table_address_length, tvb, offset, 2, ENC_BIG_ENDIAN, &address_length);
1468
99
  EAT_AND_CHECK(2,2);
1469
1470
99
  tf = proto_tree_add_item_ret_uint(info_tree, hf_address_table_length, tvb, offset, 4, ENC_BIG_ENDIAN, &table_length);
1471
99
  element_tree = proto_item_add_subtree(tf, ett_table_element);
1472
99
  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
99
  if (wccp_wccp_address_table->in_use == false) {
1478
68
    wccp_wccp_address_table->family = family;
1479
68
    wccp_wccp_address_table->table_length =  table_length;
1480
1481
68
    switch (wccp_wccp_address_table->family) {
1482
43
    case 1:
1483
43
      if (wccp_wccp_address_table->table_ipv4 == NULL)
1484
43
        wccp_wccp_address_table->table_ipv4 = (uint32_t *)
1485
43
          wmem_alloc0(pinfo->pool, wccp_wccp_address_table->table_length * 4);
1486
43
      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
68
    };
1493
68
  }
1494
1495
  /* Check if the length is valid */
1496
99
  switch (family) {
1497
62
    case 1:
1498
62
      if (address_length != 4) {
1499
62
        expert_add_info_format(pinfo, tf, &ei_wccp_length_bad,
1500
62
                               "The Address length must be 4, but I found %d for IPv4 addresses. Correcting this.",
1501
62
                               address_length);
1502
62
        address_length = 4;
1503
62
      }
1504
62
      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
35
    default:
1514
35
      expert_add_info_format(pinfo, tf, &ei_wccp_address_table_family_unknown,
1515
35
                      "Unknown address family: %u", wccp_wccp_address_table->family);
1516
35
      if (address_length % 4) {
1517
7
        expert_add_info_format(pinfo, tf, &ei_wccp_length_bad,
1518
7
                               "The Address length must be a multiple of 4. Correcting this.");
1519
7
        address_length = WS_ROUNDUP_4(address_length);
1520
7
      }
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
35
      if (address_length == 0) {
1524
21
        expert_add_info_format(pinfo, tf, &ei_wccp_length_bad,
1525
21
                               "The Address length must be at least 4. Correcting this.");
1526
21
        address_length = 4;
1527
21
      }
1528
99
  }
1529
1530
  /* now read the addresses and print/store them */
1531
1532
1.49k
  for(i=0; i<table_length; i++) {
1533
1.41k
    const char *addr;
1534
1535
1.41k
    switch (family) {
1536
1.19k
    case 1:
1537
      /* IPv4 */
1538
1.19k
      addr  =  tvb_ip_to_str(pinfo->pool, tvb, offset);
1539
1.19k
      if ((wccp_wccp_address_table->in_use == false) &&
1540
1.04k
          (wccp_wccp_address_table->table_ipv4 != NULL) &&
1541
814
          (i < wccp_wccp_address_table->table_length))
1542
367
        wccp_wccp_address_table->table_ipv4[i] = tvb_get_ipv4(tvb, offset);
1543
1.19k
      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
198
    default:
1553
198
      addr = wmem_strdup_printf(pinfo->pool, "unknown family %d", wccp_wccp_address_table->family);
1554
1.41k
    };
1555
1556
1.39k
    proto_item *pi;
1557
1558
1.39k
    pi = proto_tree_add_string_format_value(element_tree, hf_address_table_element, tvb,
1559
1.39k
                                            offset, address_length, addr,
1560
1.39k
                                            "%d: %s", i+1, addr);
1561
1.39k
    if (i > wccp_wccp_address_table->table_length)
1562
665
      expert_add_info_format(pinfo, pi, &ei_wccp_length_bad, "Ran out of space to store address");
1563
1.39k
    EAT(address_length);
1564
1.39k
  }
1565
1566
73
  wccp_wccp_address_table->in_use = true;
1567
73
  return length;
1568
99
}
1569
1570
1571
1572
1573
1574
21
#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
21
{
1581
21
  uint32_t n_web_caches, host_addr;
1582
21
  unsigned i;
1583
21
  uint8_t bucket;
1584
1585
21
  if (length < HASH_ASSIGNMENT_INFO_MIN_LEN)
1586
1
    return length - ASSIGNMENT_INFO_MIN_LEN;
1587
1588
20
  proto_tree_add_item_ret_uint(info_tree, hf_wc_view_wc_num, tvb, offset, 4, ENC_BIG_ENDIAN, &n_web_caches);
1589
20
  EAT(4);
1590
1591
263
  for (i = 0; i < n_web_caches; i++) {
1592
243
    if (length < 4)
1593
0
      return length - 4*(n_web_caches-i)-256;
1594
1595
243
    host_addr = tvb_get_ntohl(tvb,offset);
1596
243
    if (! addr_table->in_use){
1597
236
      proto_tree_add_ipv4_format(info_tree, hf_cache_ip, tvb, offset, 4, host_addr, "Web-Cache %d: IP address %s", i,
1598
236
                        decode_wccp_encoded_address(tvb, offset, pinfo, info_tree, addr_table));
1599
236
    } 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
243
    EAT(4);
1604
243
  }
1605
1606
1607
1.06k
  for (i = 0; i < 256; i++, offset++, length--) {
1608
1.04k
    if (length < 1)
1609
0
      return length - (256-i);
1610
1.04k
    bucket = tvb_get_uint8(tvb, offset);
1611
1.04k
    proto_tree_add_uint_format(info_tree, hf_bucket, tvb, offset, 1,
1612
1.04k
                        bucket, "Bucket %3d: %10s",
1613
1.04k
                        i, assignment_bucket_name(pinfo->pool, bucket));
1614
1.04k
  }
1615
20
  return length;
1616
20
}
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
36
{
1622
36
  int new_length;
1623
1624
36
  new_length=dissect_wccp2_mask_value_set_list(tvb, offset, length, pinfo, info_tree, addr_table);
1625
1626
36
  CHECK_LENGTH_ADVANCE_OFFSET(new_length);
1627
1628
32
  return length;
1629
32
}
1630
1631
1632
1633
70
#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
66
{
1640
66
  uint16_t assignment_type;
1641
66
  uint16_t assignment_length;
1642
66
  proto_item *tf=NULL;
1643
1644
66
  if (length < ALT_ASSIGNMENT_MAP_MIN_LEN )
1645
4
    return length - ALT_ASSIGNMENT_MAP_MIN_LEN ;
1646
1647
62
  proto_tree_add_item_ret_uint16(info_tree, hf_alt_assignment_map_assignment_type, tvb, offset, 2, ENC_BIG_ENDIAN, &assignment_type);
1648
62
  EAT_AND_CHECK(2,2);
1649
1650
62
  tf=proto_tree_add_item_ret_uint16(info_tree, hf_alt_assignment_map_assignment_length, tvb, offset, 2, ENC_BIG_ENDIAN, &assignment_length);
1651
62
  EAT(2);
1652
1653
62
  if (length < assignment_length)
1654
13
    expert_add_info_format(pinfo, tf, &ei_wccp_assignment_length_bad,
1655
13
                           "Assignment length is %d but only %d remain in the packet. Ignoring this for now",
1656
13
                           assignment_length, length);
1657
1658
62
  if (length > assignment_length)  {
1659
48
    expert_add_info_format(pinfo, tf, &ei_wccp_assignment_length_bad,
1660
48
                           "Assignment length is %d but %d remain in the packet. Assuming that the assignment length is wrong and setting it to %d.",
1661
48
                           assignment_length, length, length);
1662
48
    assignment_length = length;
1663
48
  }
1664
1665
62
  switch (assignment_type) {
1666
31
  case WCCP2_HASH_ASSIGNMENT_TYPE:
1667
31
    return dissect_wccp2_assignment_info(tvb, offset, assignment_length,
1668
31
                                         pinfo, info_tree, addr_table);
1669
3
  case WCCP2_MASK_ASSIGNMENT_TYPE:
1670
3
    return dissect_wccp2_mask_value_set_list(tvb, offset, assignment_length,
1671
3
                                             pinfo, info_tree, addr_table);
1672
23
  case WCCP2r1_ALT_MASK_ASSIGNMENT_TYPE:
1673
23
    return dissect_wccp2_alternate_mask_value_set_list(tvb, offset, assignment_length,
1674
23
                                                       pinfo, info_tree, addr_table);
1675
5
  default:
1676
5
    return length;
1677
62
  }
1678
62
}
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
190
{
1691
190
  proto_tree *bucket_tree;
1692
190
  int i;
1693
190
  uint8_t bucket_info;
1694
190
  int n;
1695
1696
1697
190
  bucket_tree = proto_tree_add_subtree(info_tree, tvb, offset, 8*4,
1698
190
                                    ett_hash_assignment_buckets, NULL, "Hash Assignment Data");
1699
1700
5.41k
  for (i = 0, n = 0; i < 32; i++) {
1701
5.23k
    if (length == 0) {
1702
11
      return -i-2-2;
1703
11
    }
1704
1705
5.22k
    bucket_info = tvb_get_uint8(tvb, offset);
1706
5.22k
    n = wccp_bucket_info(bucket_info, bucket_tree, n, tvb, offset);
1707
5.22k
    EAT(1);
1708
5.22k
  }
1709
1710
179
  if (length < 2){
1711
0
    return -2-2;
1712
0
  }
1713
1714
179
  return dissect_wccp2_assignment_weight_and_status_element(tvb, offset, length, pinfo, info_tree);
1715
179
}
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
20
{
1723
20
  proto_item *mask_item;
1724
20
  proto_tree *mask_tree;
1725
20
  int new_length,start;
1726
1727
1728
20
  mask_tree = proto_tree_add_subtree(info_tree, tvb, offset, 4,
1729
20
                                  ett_mask_assignment_data_element, &mask_item, "Mask Assignment Data");
1730
20
  start = offset;
1731
1732
20
  new_length=dissect_wccp2_mask_value_set_list(tvb, offset, length, pinfo, mask_tree, addr_table);
1733
1734
28
  CHECK_LENGTH_ADVANCE_OFFSET(new_length);
1735
1736
28
  if (length < 2)
1737
0
    return length-4;
1738
1739
14
  new_length =  dissect_wccp2_assignment_weight_and_status_element(tvb, offset, length, pinfo, info_tree);
1740
14
  CHECK_LENGTH_ADVANCE_OFFSET(new_length);
1741
1742
14
  proto_item_set_len(mask_item, offset-start);
1743
14
  return length;
1744
14
}
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
160
{
1784
160
  if (length < 4)
1785
2
    return length - 4;
1786
1787
1788
158
  proto_tree_add_item(info_tree, hf_assignment_weight, tvb, offset, 2, ENC_BIG_ENDIAN);
1789
158
  EAT_AND_CHECK(2,2);
1790
158
  proto_tree_add_item(info_tree, hf_assignment_status, tvb, offset, 2, ENC_BIG_ENDIAN);
1791
158
  EAT(2);
1792
158
  return length;
1793
158
}
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
214
{
1801
214
  proto_item *element_item, *header;
1802
214
  proto_tree *item_tree;
1803
1804
214
  unsigned type_of_assignment;
1805
1806
214
  int assignment_length;
1807
1808
214
  if (length < 4)
1809
1
    return length-4;
1810
1811
1812
213
  item_tree = proto_tree_add_subtree(info_tree, tvb, offset, length,
1813
213
                               ett_extended_assigment_data_element, &header, "Extended Assignment Data Element");
1814
1815
213
  type_of_assignment = tvb_get_ntohs(tvb, offset);
1816
213
  proto_tree_add_item(item_tree, hf_extended_assignment_data_type, tvb, offset, 2, ENC_BIG_ENDIAN);
1817
213
  EAT_AND_CHECK(2,2);
1818
1819
213
  assignment_length = tvb_get_ntohs(tvb,offset);
1820
213
  element_item = proto_tree_add_item(item_tree, hf_extended_assignment_data_length, tvb, offset, 2, ENC_BIG_ENDIAN);
1821
213
  EAT(2);
1822
1823
213
  if (length < assignment_length)
1824
117
    expert_add_info_format(pinfo, element_item, &ei_wccp_assignment_length_bad,
1825
117
                           "Assignment length is %d but only %d remain in the packet. Ignoring this for now",
1826
117
                           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
213
  if ((length > assignment_length) &&
1831
96
      (length == (assignment_length + 4)))
1832
2
    {
1833
2
      expert_add_info_format(pinfo, element_item, &ei_wccp_assignment_length_bad,
1834
2
                             "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
2
                             assignment_length, length, length);
1836
2
      assignment_length = length;
1837
2
    }
1838
1839
1840
213
  proto_item_set_len(header, assignment_length+4);
1841
1842
213
  switch (type_of_assignment)
1843
213
    {
1844
12
    case WCCP2_HASH_ASSIGNMENT_TYPE:
1845
12
      dissect_wccp2_hash_assignment_data_element(tvb, offset, assignment_length,
1846
12
                                                        pinfo, item_tree);
1847
12
      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
213
    }
1861
199
  return length;
1862
213
}
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
69
{
1874
69
  uint16_t capability_type;
1875
69
  uint16_t capability_val_len;
1876
69
  proto_item *te, *header, *tf;
1877
69
  proto_tree *element_tree;
1878
1879
69
  if (length < 4)
1880
0
    return length - 4;
1881
1882
69
  capability_type = tvb_get_ntohs(tvb, offset);
1883
69
  element_tree = proto_tree_add_subtree_format(info_tree, tvb, offset, -1, ett_capability_element, &te,
1884
69
                                               "Type: %s",
1885
69
                                               val_to_str(pinfo->pool, capability_type,
1886
69
                                                          capability_type_vals,
1887
69
                                                          "Unknown (0x%08X)"));
1888
69
  header = te;
1889
1890
69
  proto_tree_add_item(element_tree, hf_capability_element_type, tvb, offset, 2, ENC_BIG_ENDIAN);
1891
1892
69
  capability_val_len = tvb_get_ntohs(tvb, offset+2);
1893
69
  tf = proto_tree_add_uint(element_tree, hf_capability_element_length, tvb, offset+2, 2, capability_val_len);
1894
69
  proto_item_set_len(te, capability_val_len + 4);
1895
1896
69
  if (length < (4+capability_val_len))
1897
10
    return length - (4 + capability_val_len);
1898
1899
59
  switch (capability_type) {
1900
2
  case WCCP2_FORWARDING_METHOD:
1901
2
    dissect_32_bit_capability_flags(tvb, offset,
1902
2
                                    capability_val_len,
1903
2
                                    ett_capability_forwarding_method,
1904
2
                                    forwarding_method_flags, element_tree,
1905
2
                                    header, tf, pinfo);
1906
2
    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
1
  case WCCP2_TRANSMIT_T:
1925
1
    dissect_transmit_t_capability(tvb, te, offset,
1926
1
                                  capability_val_len,
1927
1
                                  ett_capability_transmit_t, element_tree,
1928
1
                                  tf, pinfo);
1929
1
    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
54
  default:
1938
54
    proto_tree_add_item(element_tree, hf_capability_value, tvb, offset, capability_val_len, ENC_NA);
1939
54
    break;
1940
59
  }
1941
58
  return length - 4 - capability_val_len;
1942
59
}
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
64
{
1950
64
  unsigned num_of_elem;
1951
64
  unsigned i;
1952
64
  proto_item *te;
1953
64
  proto_tree *element_tree;
1954
64
  unsigned start;
1955
1956
1957
64
  if (length < 4)
1958
1
    return length - 4;
1959
1960
63
  element_tree = proto_tree_add_subtree(info_tree, tvb, offset, 4, ett_mv_set_list, &te, "Mask/Value Set List");
1961
63
  start = offset;
1962
1963
1964
63
  num_of_elem = tvb_get_ntohl(tvb, offset);
1965
63
  proto_tree_add_item(element_tree, hf_mask_value_set_list_num_elements,
1966
63
                      tvb, offset, 4, ENC_BIG_ENDIAN);
1967
  /*  proto_tree_add_uint(element_tree, , tvb, offset, 4, num_of_elem); */
1968
63
  EAT(4);
1969
1970
181
  for (i = 0; i < num_of_elem; i++)
1971
127
    {
1972
127
      int new_length;
1973
1974
127
      new_length=dissect_wccp2_mask_value_set_element(tvb, offset, length, i, pinfo, element_tree, addr_table);
1975
1976
236
      CHECK_LENGTH_ADVANCE_OFFSET(new_length);
1977
236
    }
1978
1979
54
  proto_item_set_len(te, offset-start);
1980
54
  return length;
1981
63
}
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
215
{
1991
215
  if (length < 2)
1992
0
    return length-12;
1993
1994
215
  proto_tree_add_item(info_tree, hf_mask_element_src_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1995
215
  EAT_AND_CHECK(4,4);
1996
215
  proto_tree_add_item(info_tree, hf_mask_element_dest_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1997
1998
215
  EAT_AND_CHECK(4,2);
1999
215
  proto_tree_add_item(info_tree, hf_mask_element_src_port, tvb, offset, 2, ENC_BIG_ENDIAN);
2000
215
  EAT_AND_CHECK(2,2);
2001
213
  proto_tree_add_item(info_tree, hf_mask_element_dest_port, tvb, offset, 2, ENC_BIG_ENDIAN);
2002
213
  EAT(2);
2003
2004
213
  return length;
2005
215
}
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
37
{
2016
37
  proto_tree *list_tree;
2017
37
  unsigned num_of_val_elements;
2018
37
  unsigned i;
2019
2020
37
  if (length < 4)
2021
0
    return length - 4;
2022
2023
37
  list_tree = proto_tree_add_subtree(info_tree, tvb, offset, length,
2024
37
                               ett_alternate_mask_value_set, NULL, "Alternate Mask/Value Set List");
2025
2026
37
  num_of_val_elements = tvb_get_ntohl(tvb, offset);
2027
37
  proto_tree_add_uint(list_tree, hf_alt_assignment_mask_value_set_list_num_elements, tvb, offset, 4, num_of_val_elements);
2028
37
  EAT(4);
2029
2030
104
  for(i=0;i<num_of_val_elements;i++) {
2031
88
    int new_length;
2032
2033
88
    new_length=dissect_wccp2_alternate_mask_value_set_element(tvb, offset, length, i, pinfo, list_tree, addr_table);
2034
2035
134
    CHECK_LENGTH_ADVANCE_OFFSET(new_length);
2036
134
  }
2037
16
  return length;
2038
37
}
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
88
{
2046
88
  proto_item *tl, *header;
2047
88
  proto_tree *element_tree, *value_tree;
2048
88
  unsigned number_of_elements;
2049
88
  int new_length;
2050
88
  unsigned i;
2051
2052
88
  element_tree = proto_tree_add_subtree_format(info_tree, tvb, offset, 0,
2053
88
                               ett_alternate_mask_value_set_element, &header,
2054
88
                               "Alternate Mask/Value Set Element(%d)", el_index);
2055
2056
88
  new_length=dissect_wccp2_mask_element(tvb,offset,length,pinfo,element_tree);
2057
176
  CHECK_LENGTH_ADVANCE_OFFSET(new_length);
2058
2059
176
  if (length < 4)
2060
1
    return length - 4;
2061
2062
87
  number_of_elements  = tvb_get_ntohl(tvb, offset);
2063
87
  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
87
  value_tree = proto_item_add_subtree(tl, ett_alternate_mv_set_element_list);
2065
87
  EAT(4);
2066
2067
  /* XXX Add a bounds check for number_of_elements? */
2068
235
  for (i=0; i < number_of_elements; i++) {
2069
168
    new_length=dissect_wccp2_web_cache_value_element(tvb, offset, length, pinfo, value_tree, addr_table);
2070
306
    CHECK_LENGTH_ADVANCE_OFFSET(new_length);
2071
306
  }
2072
67
  proto_item_set_end(header, tvb, offset);
2073
2074
67
  return length;
2075
87
}
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
168
{
2081
168
  unsigned number_of_elements, seq_num;
2082
168
  proto_item *tl;
2083
168
  proto_tree *element_tree;
2084
168
  unsigned i;
2085
2086
168
  if (length < 4)
2087
1
    return length - 8;
2088
2089
167
  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
167
  element_tree = proto_item_add_subtree(tl, ett_web_cache_value_element_list);
2092
167
  EAT_AND_CHECK(4,4);
2093
2094
166
  number_of_elements  = tvb_get_ntohl(tvb, offset);
2095
166
  proto_tree_add_uint(element_tree, hf_web_cache_value_element_num_values, tvb, offset, 4, number_of_elements);
2096
166
  EAT(4);
2097
2098
1.81k
  for (i=0; i < number_of_elements; i++) {
2099
1.72k
    if (length < 4)
2100
79
      return length - 4*(number_of_elements-i);
2101
2102
1.65k
    seq_num = tvb_get_ntohl(tvb, offset);
2103
1.65k
    proto_tree_add_uint_format(element_tree, hf_web_cache_value_seq_num, tvb, offset, 4,
2104
1.65k
                        seq_num, "Value Sequence Number %d: %x", i+1, seq_num);
2105
1.65k
    EAT(4);
2106
1.65k
  }
2107
2108
87
  return length;
2109
166
}
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
3
{
2121
3
  uint32_t capability_val;
2122
3
  proto_item *tm;
2123
3
  proto_tree *method_tree;
2124
3
  int i;
2125
3
  bool first = true;
2126
2127
3
  if (capability_val_len != 4) {
2128
3
    expert_add_info_format(pinfo, length_item, &ei_wccp_capability_element_length,
2129
3
                "Value Length: %u (illegal, must be == 4)", capability_val_len);
2130
3
    return;
2131
3
  }
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
1
{
2167
1
  uint16_t upper_limit, lower_limit;
2168
1
  proto_tree *method_tree;
2169
2170
1
  if (capability_val_len != 4) {
2171
1
    expert_add_info_format(pinfo, length_item, &ei_wccp_capability_element_length,
2172
1
                "Value Length: %u (illegal, must be == 4)", capability_val_len);
2173
1
    return;
2174
1
  }
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
546
{
2255
546
  proto_tree *element_tree;
2256
2257
546
  if (length < 4)
2258
1
    return length - 16;
2259
2260
545
  element_tree = proto_tree_add_subtree_format(info_tree, tvb, offset, 16, ett_value_element, NULL, "Value Element(%u) %s",
2261
545
                           idx,decode_wccp_encoded_address(tvb, offset+4+4+2+2, pinfo, info_tree, addr_table));
2262
2263
2264
545
  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
545
  EAT_AND_CHECK(4,4);
2266
544
  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
544
  EAT_AND_CHECK(4,2);
2269
543
  proto_tree_add_item(element_tree, hf_value_element_src_port, tvb, offset, 2, ENC_BIG_ENDIAN);
2270
543
  EAT_AND_CHECK(2,2);
2271
542
  proto_tree_add_item(element_tree, hf_value_element_dest_port, tvb, offset, 2, ENC_BIG_ENDIAN);
2272
542
  EAT_AND_CHECK(2,4);
2273
2274
540
  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
540
  EAT(4);
2276
2277
540
  return length;
2278
542
}
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
127
{
2285
127
  proto_item *tl, *te;
2286
127
  proto_tree *element_tree, *value_tree;
2287
127
  unsigned num_of_val_elements;
2288
127
  unsigned i;
2289
127
  int new_length;
2290
2291
127
  element_tree = proto_tree_add_subtree_format(info_tree, tvb, offset, 0,
2292
127
                           ett_mv_set_element, &tl, "Mask/Value Set Element(%d)", idx);
2293
2294
127
  new_length = dissect_wccp2_mask_element(tvb,offset,length,pinfo,element_tree);
2295
250
  CHECK_LENGTH_ADVANCE_OFFSET(new_length);
2296
2297
250
  if (length < 4)
2298
1
    return length-4;
2299
2300
124
  num_of_val_elements = tvb_get_ntohl(tvb, offset);
2301
124
  te = proto_tree_add_uint(element_tree, hf_mask_value_set_element_value_element_num, tvb, offset, 4, num_of_val_elements);
2302
2303
124
  value_tree = proto_item_add_subtree(te, ett_mv_set_value_list);
2304
124
  EAT(4);
2305
2306
664
  for (i = 0; i < num_of_val_elements; i++)
2307
546
    {
2308
546
      new_length=dissect_wccp2_value_element(tvb, offset, length, i, pinfo,  value_tree, addr_table);
2309
2310
1.08k
      CHECK_LENGTH_ADVANCE_OFFSET(new_length);
2311
1.08k
    }
2312
2313
118
  proto_item_set_len(tl, 16+num_of_val_elements*16);
2314
2315
118
  return length;
2316
124
}
2317
2318
64
#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
63
{
2325
63
  uint16_t assignment_type;
2326
63
  uint16_t assignment_length;
2327
63
  proto_item *tf=NULL;
2328
2329
63
  uint32_t n_routers;
2330
63
  unsigned i;
2331
63
  proto_tree *element_tree;
2332
63
  int new_length;
2333
2334
2335
63
  if (length < ALT_ASSIGNMENT_INFO_MIN_LEN)
2336
1
    return length - ALT_ASSIGNMENT_INFO_MIN_LEN;
2337
2338
62
  proto_tree_add_item_ret_uint16(info_tree, hf_alt_assignment_info_assignment_type, tvb, offset, 2, ENC_BIG_ENDIAN, &assignment_type);
2339
62
  EAT_AND_CHECK(2,2);
2340
2341
62
  tf=proto_tree_add_item_ret_uint16(info_tree, hf_alt_assignment_info_assignment_length, tvb, offset, 2, ENC_BIG_ENDIAN, &assignment_length);
2342
62
  EAT(2);
2343
2344
62
  if (length < assignment_length)
2345
10
    expert_add_info_format(pinfo, tf, &ei_wccp_assignment_length_bad,
2346
10
                           "Assignment length is %d but only %d remain in the packet. Ignoring this for now",
2347
10
                           assignment_length, length);
2348
2349
62
  if (length > assignment_length)  {
2350
52
    expert_add_info_format(pinfo, tf, &ei_wccp_assignment_length_bad,
2351
52
                           "Assignment length is %d but %d remain in the packet. Assuming that the assignment length is wrong and setting it to %d.",
2352
52
                           assignment_length, length, length);
2353
52
  }
2354
2355
62
  new_length=dissect_wccp2_assignment_key_element(tvb, offset, length, pinfo,  info_tree, addr_table);
2356
120
  CHECK_LENGTH_ADVANCE_OFFSET(new_length);
2357
2358
120
  n_routers = tvb_get_ntohl(tvb, offset);
2359
120
  proto_tree_add_uint(info_tree, hf_alt_assignment_info_num_routers, tvb, offset, 4, n_routers);
2360
120
  EAT(4);
2361
2362
270
  for (i = 0; i < n_routers; i++) {
2363
214
    if (length < 12)
2364
4
      return length - 12*(n_routers-i);
2365
2366
210
    element_tree = proto_tree_add_subtree_format(info_tree, tvb, offset, 12,
2367
210
                             ett_router_alt_assignment_element, NULL,
2368
210
                             "Router %d Assignment Element: IP address %s", i,
2369
210
                             decode_wccp_encoded_address(tvb, offset, pinfo, info_tree, addr_table));
2370
2371
210
    dissect_wccp2_router_assignment_element(tvb, offset, length , pinfo, element_tree, addr_table);
2372
210
    EAT(12);
2373
210
  }
2374
2375
56
  switch (assignment_type) {
2376
21
  case WCCP2_HASH_ASSIGNMENT_TYPE:
2377
21
    return dissect_wccp2_hash_assignment_info(tvb, offset, length,
2378
21
                                              pinfo, info_tree, addr_table);
2379
5
  case WCCP2_MASK_ASSIGNMENT_TYPE:
2380
5
    return dissect_wccp2_mask_value_set_list(tvb, offset, length,
2381
5
                                             pinfo, info_tree, addr_table);
2382
14
  case WCCP2r1_ALT_MASK_ASSIGNMENT_TYPE:
2383
14
    return dissect_wccp2_alternate_mask_value_set_list(tvb, offset, length,
2384
14
                                                       pinfo, info_tree, addr_table);
2385
3
  default:
2386
3
    return length;
2387
56
  }
2388
56
}
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
374
{
2395
374
  uint16_t type;
2396
374
  uint16_t item_length;
2397
374
  proto_item *tf;
2398
374
  proto_tree *info_tree;
2399
374
  int ett;
2400
374
  int (*dissector)(tvbuff_t *, int, int, packet_info *, proto_tree *, wccp_address_table*);
2401
2402
  /* check if all required fields are there */
2403
374
  bool wccp2_security_info;
2404
374
  bool wccp2_service_info;
2405
374
  bool wccp2_router_id_info;
2406
374
  bool wccp2_wc_id_info;
2407
374
  bool wccp2_rtr_view_info;
2408
374
  bool wccp2_wc_view_info;
2409
374
  bool wccp2_redirect_assignment;
2410
374
  bool wccp2_query_info;
2411
374
  bool wccp2_capabilities_info;
2412
374
  bool wccp2_alt_assignment;
2413
374
  bool wccp2_assign_map;
2414
374
  bool wccp2_command_extension;
2415
374
  bool wccp2r1_alt_assignment_map;
2416
374
  wccp_address_table wccp_wccp_address_table = {false, -1, -1, 0, NULL, NULL};
2417
2418
374
  wccp2_security_info=false;
2419
374
  wccp2_service_info=false;
2420
374
  wccp2_router_id_info=false;
2421
374
  wccp2_wc_id_info=false;
2422
374
  wccp2_rtr_view_info=false;
2423
374
  wccp2_wc_view_info=false;
2424
374
  wccp2_redirect_assignment=false;
2425
374
  wccp2_query_info=false;
2426
374
  wccp2_capabilities_info=false;
2427
374
  wccp2_alt_assignment=false;
2428
374
  wccp2_assign_map=false;
2429
374
  wccp2_command_extension=false;
2430
374
  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
374
  find_wccp_address_table(tvb,offset,pinfo,wccp_tree, &wccp_wccp_address_table);
2436
2437
1.44k
  while (tvb_reported_length_remaining(tvb, offset) > 0) {
2438
1.07k
    type = tvb_get_ntohs(tvb, offset);
2439
1.07k
    switch (type) {
2440
2441
483
    case WCCP2_SECURITY_INFO:
2442
483
      wccp2_security_info=true;
2443
483
      ett = ett_security_info;
2444
483
      dissector = dissect_wccp2_security_info;
2445
483
      break;
2446
2447
8
    case WCCP2_SERVICE_INFO:
2448
8
      wccp2_service_info=true;
2449
8
      ett = ett_service_info;
2450
8
      dissector = dissect_wccp2_service_info;
2451
8
      break;
2452
2453
19
    case WCCP2_ROUTER_ID_INFO:
2454
19
      wccp2_router_id_info=true;
2455
19
      ett = ett_router_identity_info;
2456
19
      dissector = dissect_wccp2_router_identity_info;
2457
19
      break;
2458
2459
6
    case WCCP2_WC_ID_INFO:
2460
6
      wccp2_wc_id_info=true;
2461
6
      ett = ett_wc_identity_info;
2462
6
      dissector = dissect_wccp2_wc_identity_info;
2463
6
      break;
2464
2465
74
    case WCCP2_RTR_VIEW_INFO:
2466
74
      wccp2_rtr_view_info=true;
2467
74
      ett = ett_router_view_info;
2468
74
      dissector = dissect_wccp2_router_view_info;
2469
74
      break;
2470
2471
27
    case WCCP2_WC_VIEW_INFO:
2472
27
      wccp2_wc_view_info=true;
2473
27
      ett = ett_wc_view_info;
2474
27
      dissector = dissect_wccp2_web_cache_view_info;
2475
27
      break;
2476
2477
38
    case WCCP2_REDIRECT_ASSIGNMENT:
2478
38
      wccp2_redirect_assignment=true;
2479
38
      ett = ett_router_assignment_info;
2480
38
      dissector = dissect_wccp2_assignment_info;
2481
38
      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
12
    case WCCP2_CAPABILITIES_INFO:
2490
12
      wccp2_capabilities_info=true;
2491
12
      ett = ett_capabilities_info;
2492
12
      dissector = dissect_wccp2_capability_info;
2493
12
      break;
2494
2495
64
    case WCCP2_ALT_ASSIGNMENT:
2496
64
      wccp2_alt_assignment=true;
2497
64
      ett = ett_alt_assignment_info;
2498
64
      dissector = dissect_wccp2_alternate_assignment_info;
2499
64
      break;
2500
2501
66
    case WCCP2r1_ALT_ASSIGNMENT_MAP:
2502
66
      wccp2r1_alt_assignment_map=true;
2503
66
      ett = ett_alt_assignment_map;
2504
66
      dissector = dissect_wccp2r1_alt_assignment_map_info;
2505
66
      break;
2506
2507
46
    case WCCP2r1_ADDRESS_TABLE:
2508
46
      ett = ett_address_table;
2509
46
      dissector = dissect_wccp2r1_address_table_info;
2510
46
      break;
2511
2512
36
    case WCCP2_ASSIGN_MAP:
2513
36
      wccp2_assign_map=true;
2514
36
      ett = ett_assignment_map;
2515
36
      dissector = dissect_wccp2_assignment_map;
2516
36
      break;
2517
22
    case WCCP2_COMMAND_EXTENSION:
2518
22
      wccp2_command_extension=true;
2519
22
      ett = ett_command_extension;
2520
22
      dissector = dissect_wccp2_command_extension;
2521
22
      break;
2522
2523
165
    default:
2524
165
      ett = ett_unknown_info;
2525
165
      dissector = NULL;
2526
165
      break;
2527
1.07k
    }
2528
2529
1.07k
    info_tree = proto_tree_add_subtree(wccp_tree, tvb, offset, -1, ett, &tf,
2530
1.07k
                             val_to_str(pinfo->pool, type, info_type_vals, "Unknown info type (%u)"));
2531
2532
1.07k
    proto_tree_add_item(info_tree, hf_item_type, tvb, offset, 2, ENC_BIG_ENDIAN);
2533
2534
1.07k
    proto_tree_add_item_ret_uint16(info_tree, hf_item_length, tvb, offset+2, 2, ENC_BIG_ENDIAN, &item_length);
2535
2536
1.07k
    offset += 4;
2537
2538
1.07k
    if (dissector != NULL) {
2539
901
      int remaining_item_length = (*dissector)(tvb, offset, item_length, pinfo, info_tree, &wccp_wccp_address_table);
2540
2541
      /* warn if we left bytes */
2542
901
      if (remaining_item_length > 0)
2543
104
        expert_add_info_format(pinfo, tf, &ei_wccp_length_bad,
2544
104
                               "The item is %d bytes too long",
2545
104
                               remaining_item_length);
2546
2547
      /* error if we needed more bytes */
2548
901
      if (remaining_item_length < 0)
2549
580
        expert_add_info_format(pinfo, tf, &ei_wccp_length_bad,
2550
580
                               "The item is %d bytes too short",
2551
580
                               -remaining_item_length);
2552
2553
      /* we assume that the item length is correct and jump forward */
2554
901
    } else {
2555
171
      proto_tree_add_item(info_tree, hf_item_data, tvb, offset, item_length, ENC_NA);
2556
171
    }
2557
2558
1.07k
    offset += item_length;
2559
1.07k
    proto_item_set_end(tf, tvb, offset);
2560
1.07k
  }
2561
2562
2563
  /* we're done. Check if we got all the required components */
2564
2565
372
  switch (message_type) {
2566
10
  case WCCP2_HERE_I_AM:
2567
10
    if (!wccp2_security_info)
2568
2
      expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_security_info);
2569
10
    if (!wccp2_service_info)
2570
9
      expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_service_info);
2571
10
    if (wccp2_router_id_info)
2572
1
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_router_id_info);
2573
10
    if (!wccp2_wc_id_info)
2574
10
      expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_wc_id_info);
2575
10
    if (wccp2_rtr_view_info)
2576
2
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_rtr_view_info);
2577
10
    if (!wccp2_wc_view_info)
2578
9
      expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_wc_view_info);
2579
10
    if (wccp2_redirect_assignment)
2580
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_redirect_assignment);
2581
10
    if (wccp2_query_info)
2582
1
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_query_info);
2583
10
    if (wccp2_alt_assignment)
2584
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_alt_assignment);
2585
10
    if (wccp2_assign_map)
2586
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_assign_map);
2587
10
    if (wccp2r1_alt_assignment_map)
2588
1
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_alt_assignment_map);
2589
10
    break;
2590
4
  case WCCP2_I_SEE_YOU:
2591
4
    if (!wccp2_security_info)
2592
1
      expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_security_info);
2593
4
    if (!wccp2_service_info)
2594
3
      expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_service_info);
2595
4
    if (!wccp2_router_id_info)
2596
4
      expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_router_id_info);
2597
4
    if (wccp2_wc_id_info)
2598
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_wc_id_info);
2599
4
    if (!wccp2_rtr_view_info)
2600
4
      expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_rtr_view_info);
2601
4
    if (wccp2_wc_view_info)
2602
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_wc_view_info);
2603
4
    if (wccp2_redirect_assignment)
2604
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_redirect_assignment);
2605
4
    if (wccp2_query_info)
2606
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_query_info);
2607
4
    if (wccp2r1_alt_assignment_map)
2608
1
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_alt_assignment_map);
2609
4
    break;
2610
2611
6
  case WCCP2_REMOVAL_QUERY:
2612
6
    if (!wccp2_security_info)
2613
1
      expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_security_info);
2614
6
    if (!wccp2_service_info)
2615
6
      expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_service_info);
2616
6
    if (wccp2_router_id_info)
2617
1
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_router_id_info);
2618
6
    if (wccp2_wc_id_info)
2619
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_wc_id_info);
2620
6
    if (wccp2_rtr_view_info)
2621
1
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_rtr_view_info);
2622
6
    if (wccp2_wc_view_info)
2623
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_wc_view_info);
2624
6
    if (wccp2_redirect_assignment)
2625
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_redirect_assignment);
2626
6
    if (!wccp2_query_info)
2627
6
      expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_query_info);
2628
6
    if (wccp2_capabilities_info)
2629
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_capabilities_info);
2630
6
    if (wccp2_alt_assignment)
2631
2
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_alt_assignment);
2632
6
    if (wccp2_assign_map)
2633
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_assign_map);
2634
6
    if (wccp2_command_extension)
2635
0
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_command_extension);
2636
6
    if (wccp2r1_alt_assignment_map)
2637
1
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_alt_assignment_map);
2638
6
    break;
2639
2640
58
  case WCCP2_REDIRECT_ASSIGN:
2641
58
    if (!wccp2_security_info)
2642
25
      expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_security_info);
2643
58
    if (!wccp2_service_info)
2644
55
      expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_service_info);
2645
58
    if (wccp2_router_id_info)
2646
1
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_router_id_info);
2647
58
    if (wccp2_wc_id_info)
2648
1
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_wc_id_info);
2649
58
    if (wccp2_rtr_view_info)
2650
5
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_rtr_view_info);
2651
58
    if (wccp2_wc_view_info)
2652
3
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_wc_view_info);
2653
58
    if (wccp2_query_info)
2654
4
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_query_info);
2655
58
    if (wccp2_capabilities_info)
2656
8
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_capabilities_info);
2657
58
    if (! (wccp2_assign_map || wccp2r1_alt_assignment_map || wccp2_alt_assignment || wccp2_redirect_assignment))
2658
29
      expert_add_info(pinfo, wccp_tree, &ei_wccp_missing_assignment);
2659
58
    if (wccp2_command_extension)
2660
5
      expert_add_info(pinfo, wccp_tree, &ei_wccp_contains_command_extension);
2661
58
    break;
2662
372
  }
2663
372
}
2664
2665
static int
2666
dissect_wccp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
2667
489
{
2668
489
  int offset = 0;
2669
489
  proto_tree *wccp_tree = NULL;
2670
489
  proto_item *wccp_tree_item;
2671
489
  uint32_t wccp_message_type;
2672
489
  uint16_t length;
2673
489
  unsigned wccp2_length;
2674
489
  proto_item *length_item;
2675
489
  uint32_t cache_count;
2676
489
  uint32_t ipaddr;
2677
489
  unsigned i;
2678
489
  uint8_t bucket;
2679
2680
489
  wccp_message_type = tvb_get_ntohl(tvb, offset);
2681
2682
  /* Check if this is really a WCCP message */
2683
489
  if (try_val_to_str(wccp_message_type, wccp_type_vals) == NULL)
2684
72
    return 0;
2685
2686
417
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "WCCP");
2687
2688
417
  col_add_str(pinfo->cinfo, COL_INFO, val_to_str(pinfo->pool, wccp_message_type,
2689
417
                                                   wccp_type_vals, "Unknown WCCP message (%u)"));
2690
2691
417
  wccp_tree_item = proto_tree_add_item(tree, proto_wccp, tvb, offset, -1, ENC_NA);
2692
417
  wccp_tree = proto_item_add_subtree(wccp_tree_item, ett_wccp);
2693
2694
417
  proto_tree_add_uint(wccp_tree, hf_wccp_message_type, tvb, offset, 4, wccp_message_type);
2695
417
  offset += 4;
2696
2697
417
  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
18
    case WCCP_I_SEE_YOU:
2710
18
      proto_tree_add_item(wccp_tree, hf_wccp_version, tvb,
2711
18
                          offset, 4, ENC_BIG_ENDIAN);
2712
18
      offset += 4;
2713
18
      proto_tree_add_item(wccp_tree, hf_change_num, tvb, offset,
2714
18
                          4, ENC_BIG_ENDIAN);
2715
18
      offset += 4;
2716
18
      proto_tree_add_item(wccp_tree, hf_recvd_id, tvb, offset,
2717
18
                          4, ENC_BIG_ENDIAN);
2718
18
      offset += 4;
2719
18
      cache_count = tvb_get_ntohl(tvb, offset);
2720
18
      proto_tree_add_uint(wccp_tree, hf_wc_num, tvb, offset, 4, cache_count);
2721
18
      offset += 4;
2722
85
      for (i = 0; i < cache_count; i++) {
2723
67
        offset = dissect_web_cache_list_entry(tvb, offset, i,
2724
67
                                              wccp_tree);
2725
67
      }
2726
18
      break;
2727
2728
23
    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
23
      proto_tree_add_item(wccp_tree, hf_recvd_id, tvb, offset,
2738
23
                          4, ENC_BIG_ENDIAN);
2739
23
      offset += 4;
2740
23
      cache_count = tvb_get_ntohl(tvb, offset);
2741
23
      proto_tree_add_uint(wccp_tree, hf_wc_num, tvb, offset, 4, cache_count);
2742
23
      offset += 4;
2743
416
      for (i = 0; i < cache_count; i++) {
2744
393
        ipaddr = tvb_get_ipv4(tvb, offset);
2745
393
        proto_tree_add_ipv4_format(wccp_tree,
2746
393
                                   hf_cache_ip, tvb, offset, 4,
2747
393
                                   ipaddr,
2748
393
                                   "Web Cache %d IP Address: %s", i,
2749
393
                                   tvb_ip_to_str(pinfo->pool, tvb, offset));
2750
393
        offset += 4;
2751
393
      }
2752
2753
1.20k
      for (i = 0; i < 256; i++) {
2754
1.18k
          bucket = tvb_get_uint8(tvb, offset);
2755
1.18k
          if (bucket == 0xff) {
2756
293
              proto_tree_add_uint_format(wccp_tree, hf_bucket, tvb, offset, 1,
2757
293
                  bucket, "Bucket %d: Unassigned", i);
2758
890
          } else {
2759
890
              proto_tree_add_uint_format(wccp_tree, hf_bucket, tvb, offset, 1,
2760
890
                    bucket, "Bucket %d: %d", i, bucket);
2761
890
          }
2762
1.18k
        offset++;
2763
1.18k
      }
2764
23
      break;
2765
2766
19
    case WCCP2_HERE_I_AM:
2767
28
    case WCCP2_I_SEE_YOU:
2768
36
    case WCCP2_REMOVAL_QUERY:
2769
374
    case WCCP2_REDIRECT_ASSIGN:
2770
374
    default:    /* assume unknown packets are v2 */
2771
      /* 5.5 WCCP Message Header */
2772
2773
374
      proto_tree_add_item(wccp_tree, hf_message_header_version, tvb, offset, 2,
2774
374
                          ENC_BIG_ENDIAN);
2775
374
      offset += 2;
2776
2777
374
      length = tvb_get_ntohs(tvb, offset);
2778
374
      length_item = proto_tree_add_uint(wccp_tree, hf_message_header_length, tvb, offset, 2, length);
2779
374
      offset += 2;
2780
2781
      /* Is the length plus the length of the data preceding it longer than
2782
         the length of our packet? */
2783
374
      wccp2_length = tvb_reported_length_remaining(tvb, offset);
2784
374
      if (length > wccp2_length) {
2785
372
        expert_add_info_format(pinfo, length_item, &ei_wccp_length_bad,
2786
372
                               "The length as specified by the length field is bigger than the length of the packet");
2787
372
        length = wccp2_length;
2788
372
      } else {
2789
        /* Truncate the packet to the specified length. */
2790
2
        tvb_set_reported_length(tvb, offset + length);
2791
2
      }
2792
374
      proto_item_set_len(wccp_tree_item, offset + length);
2793
374
      dissect_wccp2_info(tvb, offset, pinfo, wccp_tree, wccp_message_type);
2794
374
      break;
2795
417
  }
2796
2797
81
  return tvb_captured_length(tvb);
2798
417
}
2799
2800
2801
2802
/* End of utility functions */
2803
2804
void
2805
proto_register_wccp(void)
2806
16
{
2807
16
  static hf_register_info hf[] = {
2808
16
    { &hf_wccp_message_type,
2809
16
      { "WCCP Message Type", "wccp.message", FT_UINT32, BASE_DEC, VALS(wccp_type_vals), 0x0,
2810
16
        "The WCCP message that was sent", HFILL }
2811
16
    },
2812
16
    { &hf_wccp_version,
2813
16
      { "WCCP Version", "wccp.version", FT_UINT32, BASE_HEX, VALS(wccp_version_val), 0x0,
2814
16
        "The WCCP version", HFILL }
2815
16
    },
2816
16
    { &hf_bucket,
2817
16
      { "Bucket", "wccp.bucket", FT_UINT8, BASE_DEC, 0x0, 0x0,
2818
16
        NULL, HFILL }
2819
16
    },
2820
16
    { &hf_bucket_bit,
2821
16
      { "Bucket", "wccp.bucket_bit", FT_UINT8, BASE_DEC, 0x0, 0x0,
2822
16
        NULL, HFILL }
2823
16
    },
2824
16
    { &hf_message_header_version,
2825
16
      { "WCCP Version (>=2)", "wccp.message_header_version", FT_UINT16, BASE_HEX, NULL, 0x0,
2826
16
        "The WCCP version for version 2 and above", HFILL }
2827
16
    },
2828
16
    { &hf_hash_revision,
2829
16
      { "Hash Revision", "wccp.hash_revision", FT_UINT32, BASE_DEC, 0x0, 0x0,
2830
16
        "The cache hash revision", HFILL }
2831
16
    },
2832
16
    { &hf_change_num,
2833
16
      { "Change Number", "wccp.change_num", FT_UINT32, BASE_DEC, 0x0, 0x0,
2834
16
        "The Web-Cache list entry change number", HFILL }
2835
16
    },
2836
16
    { &hf_hash_flag,
2837
16
      { "Flags", "wccp.hash_flag", FT_UINT32, BASE_HEX, 0x0, 0x0,
2838
16
        NULL, HFILL }
2839
16
    },
2840
16
    { &hf_hash_flag_u,
2841
16
      { "Hash information", "wccp.hash_flag.u", FT_BOOLEAN, 32, TFS(&tfs_historical_current), 0x00010000,
2842
16
        NULL, HFILL }
2843
16
    },
2844
16
    { &hf_recvd_id,
2845
16
      { "Received ID", "wccp.recvd_id", FT_UINT32, BASE_DEC, 0x0, 0x0,
2846
16
        "The number of I_SEE_YOU's that have been sent", HFILL }
2847
16
    },
2848
16
    { &hf_cache_ip,
2849
16
      { "Web Cache IP address", "wccp.cache_ip", FT_IPv4, BASE_NONE, NULL, 0x0,
2850
16
        "The IP address of a Web cache", HFILL }
2851
16
    },
2852
16
    { &hf_wc_num,
2853
16
      { "Number of Web Caches", "wccp.wc_num", FT_UINT32, BASE_DEC, 0x0, 0x0,
2854
16
        NULL, HFILL }
2855
16
    },
2856
16
    { &hf_message_header_length,
2857
16
      { "Length", "wccp.message_header_length", FT_UINT16, BASE_DEC, 0x0, 0x0,
2858
16
        NULL, HFILL }
2859
16
    },
2860
16
    { &hf_item_length,
2861
16
      { "Length", "wccp.item_length", FT_UINT16, BASE_DEC, 0x0, 0x0,
2862
16
        "The Length of the WCCPv2 item", HFILL }
2863
16
    },
2864
16
    { &hf_item_type,
2865
16
      { "Type", "wccp.item_type", FT_UINT16, BASE_DEC, VALS(info_type_vals), 0x0,
2866
16
        "The type of the WCCPv2 item", HFILL }
2867
16
    },
2868
16
    { &hf_item_data,
2869
16
      { "Data", "wccp.item_data", FT_BYTES, BASE_NONE, 0x0, 0x0,
2870
16
        "The data for an unknown item type", HFILL }
2871
16
    },
2872
16
    { &hf_security_info_option,
2873
16
      { "Security Option", "wccp.security_info_option", FT_UINT32, BASE_DEC, VALS(security_option_vals), 0x0,
2874
16
        NULL, HFILL }
2875
16
    },
2876
16
    { &hf_security_info_md5_checksum,
2877
16
      { "MD5 checksum (not checked)", "wccp.security_md5_checksum", FT_BYTES, BASE_NONE, 0x0, 0x0,
2878
16
        NULL, HFILL }
2879
16
    },
2880
16
    { &hf_command_element_type,
2881
16
      {"Command Extension Type", "wccp.command_element_type", FT_UINT16, BASE_DEC, VALS(wccp_command_type_vals), 0x0,
2882
16
       NULL, HFILL }
2883
16
    },
2884
16
    { &hf_command_element_length,
2885
16
      {"Command Extension Length", "wccp.command_element_length", FT_UINT16, BASE_DEC, NULL, 0x0,
2886
16
       NULL, HFILL }
2887
16
    },
2888
16
    { &hf_command_length,
2889
16
      {"Command Length", "wccp.command_length", FT_UINT16, BASE_DEC, NULL, 0x0,
2890
16
       NULL, HFILL }
2891
16
    },
2892
16
    { &hf_command_element_shutdown_ip_index,
2893
16
      {"Command Element Shutdown IP", "wccp.command_element_shutdown_ip_Address.index", FT_UINT32, BASE_HEX, NULL, 0x0,
2894
16
       NULL, HFILL }
2895
16
    },
2896
16
    { &hf_command_element_shutdown_ipv4,
2897
16
      {"Command Element Shutdown IP", "wccp.command_element_shutdown_ip_address.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
2898
16
       NULL, HFILL }
2899
16
    },
2900
16
    { &hf_command_element_shutdown_ipv6,
2901
16
      {"Command Element Shutdown IP", "wccp.command_element_shutdown_ip_address.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
2902
16
       NULL, HFILL }
2903
16
    },
2904
16
    { &hf_command_unknown,
2905
16
      {"Unknown Command", "wccp.command_unknown", FT_NONE, BASE_NONE, NULL, 0x0,
2906
16
       NULL, HFILL }
2907
16
    },
2908
16
    { &hf_service_info_type,
2909
16
      { "Service Type", "wccp.service_info_type", FT_UINT8, BASE_DEC, VALS(service_type_vals), 0x0,
2910
16
        NULL, HFILL }
2911
16
    },
2912
16
    { &hf_service_info_id_standard,
2913
16
      { "WCCP Service ID (Standard)", "wccp.service_info_std_id", FT_UINT8, BASE_DEC, VALS(service_id_vals) , 0x0,
2914
16
        "The WCCP Service id (Standard)", HFILL }
2915
16
    },
2916
16
    { &hf_service_info_id_dynamic,
2917
16
      { "WCCP Service ID ( Dynamic)", "wccp.service_info_dyn_id", FT_UINT8, BASE_DEC, NULL , 0x0,
2918
16
        "The WCCP Service id (Dynamic)", HFILL }
2919
16
    },
2920
16
    { &hf_service_info_priority,
2921
16
      { "Priority (highest is 255)", "wccp.service_info_priority", FT_UINT8, BASE_DEC, NULL, 0x0,
2922
16
        NULL, HFILL }
2923
16
    },
2924
16
    { &hf_service_info_protocol,
2925
16
      { "Protocol", "wccp.service_info_protocol", FT_UINT8, BASE_DEC | BASE_EXT_STRING, &ipproto_val_ext, 0x0,
2926
16
        NULL, HFILL }
2927
16
    },
2928
16
    { &hf_service_info_flags,
2929
16
      { "Flags", "wccp.service_info_flags", FT_UINT32, BASE_HEX, 0x0, 0x0,
2930
16
        NULL, HFILL }
2931
16
    },
2932
16
    { &hf_service_info_flags_src_ip_hash,
2933
16
      { "Source IP address in primary hash", "wccp.service_info_flag.src_ip_hash", FT_BOOLEAN, 32, TFS(&tfs_used_notused), WCCP2_SI_SRC_IP_HASH,
2934
16
        NULL, HFILL }
2935
16
    },
2936
16
    { &hf_service_info_flags_dest_ip_hash,
2937
16
      { "Destination IP address in primary hash", "wccp.service_info_flag.dest_ip_hash", FT_BOOLEAN, 32, TFS(&tfs_used_notused), WCCP2_SI_DST_IP_HASH,
2938
16
        NULL, HFILL }
2939
16
    },
2940
16
    { &hf_service_info_flags_src_port_hash,
2941
16
      { "Source port in primary hash", "wccp.service_info_flag.src_port_hash", FT_BOOLEAN, 32, TFS(&tfs_used_notused), WCCP2_SI_SRC_PORT_HASH,
2942
16
        NULL, HFILL }
2943
16
    },
2944
16
    { &hf_service_info_flags_dest_port_hash,
2945
16
      { "Destination port in primary hash", "wccp.service_info_flag.dest_port_hash", FT_BOOLEAN, 32, TFS(&tfs_used_notused), WCCP2_SI_DST_PORT_HASH,
2946
16
        NULL, HFILL }
2947
16
    },
2948
16
    { &hf_service_info_flags_ports_defined,
2949
16
      { "Ports", "wccp.service_info_flag.ports_defined", FT_BOOLEAN, 32, TFS(&tfs_defined_not_defined), WCCP2_SI_PORTS_DEFINED,
2950
16
        NULL, HFILL }
2951
16
    },
2952
16
    { &hf_service_info_flags_ports_source,
2953
16
      { "Ports refer to", "wccp.service_info_flag.ports_source", FT_BOOLEAN, 32, TFS(&tfs_src_dest_port), WCCP2_SI_PORTS_SOURCE,
2954
16
        NULL, HFILL }
2955
16
    },
2956
16
    { &hf_service_info_flags_redirect_only_protocol_0,
2957
16
      { "Redirect only protocol 0", "wccp.service_info_flag.redirect_only_protocol_0", FT_BOOLEAN, 32, TFS(&tfs_redirect_protocol0), WCCP2r1_SI_REDIRECT_ONLY_PROTOCOL_0,
2958
16
        NULL, HFILL }
2959
16
    },
2960
16
    { &hf_service_info_flags_src_ip_alt_hash,
2961
16
      { "Source IP address in secondary hash", "wccp.service_info_flag.src_ip_alt_hash", FT_BOOLEAN, 32, TFS(&tfs_used_notused), WCCP2_SI_SRC_IP_ALT_HASH,
2962
16
        NULL, HFILL }
2963
16
    },
2964
16
    { &hf_service_info_flags_dest_ip_alt_hash,
2965
16
      { "Destination IP address in secondary hash", "wccp.service_info_flag.dest_ip_alt_hash", FT_BOOLEAN, 32, TFS(&tfs_used_notused), WCCP2_SI_DST_IP_ALT_HASH,
2966
16
        NULL, HFILL }
2967
16
    },
2968
16
    { &hf_service_info_flags_src_port_alt_hash,
2969
16
      { "Source port in secondary hash", "wccp.service_info_flag.src_port_alt_hash", FT_BOOLEAN, 32, TFS(&tfs_used_notused), WCCP2_SI_SRC_PORT_ALT_HASH,
2970
16
        NULL, HFILL }
2971
16
    },
2972
16
    { &hf_service_info_flags_dest_port_alt_hash,
2973
16
      { "Destination port in secondary hash", "wccp.service_info_flag.dest_port_alt_hash", FT_BOOLEAN, 32, TFS(&tfs_used_notused), WCCP2_SI_DST_PORT_ALT_HASH,
2974
16
        NULL, HFILL }
2975
16
    },
2976
16
    { &hf_service_info_flags_reserved,
2977
16
      { "Reserved, should be 0", "wccp.service_info_flag.reserved", FT_UINT32, BASE_HEX, NULL, 0xFFFFF000,
2978
16
        NULL, HFILL }
2979
16
    },
2980
16
    { &hf_service_info_source_port,
2981
16
      { "Source Port", "wccp.service_info_source_port", FT_UINT16, BASE_DEC, NULL, 0x0,
2982
16
        NULL, HFILL }
2983
16
    },
2984
16
    { &hf_service_info_destination_port,
2985
16
      { "Destination Port", "wccp.service_info_destination_port", FT_UINT16, BASE_DEC, NULL, 0x0,
2986
16
        NULL, HFILL }
2987
16
    },
2988
16
    { &hf_router_identity_ip_index,
2989
16
      { "IP Address", "wccp.router_identity.ip_address.index", FT_UINT32, BASE_DEC, NULL, 0x0,
2990
16
        NULL, HFILL }
2991
16
    },
2992
16
    { &hf_router_identity_ipv4,
2993
16
      { "IP Address", "wccp.router_identity.ip_address.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
2994
16
        NULL, HFILL }
2995
16
    },
2996
16
    { &hf_router_identity_ipv6,
2997
16
      { "IP Address", "wccp.router_identity.ip_address.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
2998
16
        NULL, HFILL }
2999
16
    },
3000
16
    { &hf_router_identity_receive_id,
3001
16
      { "Received ID", "wccp.router_identity.receive_id", FT_UINT32, BASE_DEC, 0x0, 0x0,
3002
16
        NULL, HFILL }
3003
16
    },
3004
16
    { &hf_router_identity_send_to_ip_index,
3005
16
      { "Sent To IP Address", "wccp.router_identity.send_to_ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3006
16
        NULL, HFILL }
3007
16
    },
3008
16
    { &hf_router_identity_send_to_ipv4,
3009
16
      { "Sent To IP Address", "wccp.router_identity.send_to_ip.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3010
16
        NULL, HFILL }
3011
16
    },
3012
16
    { &hf_router_identity_send_to_ipv6,
3013
16
      { "Sent To IP Address", "wccp.router_identity.send_to_ip.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3014
16
        NULL, HFILL }
3015
16
    },
3016
16
    { &hf_router_identity_received_from_num,
3017
16
      { "Number of Received From IP addresses (Webcache to which the message is directed)", "wccp.router.num_recv_ip", FT_UINT32, BASE_DEC, 0x0, 0x0,
3018
16
        NULL, HFILL }
3019
16
    },
3020
16
    { &hf_web_cache_identity_index,
3021
16
      { "Web-Cache IP Address", "wccp.web_cache_identity.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3022
16
        NULL, HFILL }
3023
16
    },
3024
16
    { &hf_web_cache_identity_ipv4,
3025
16
      { "Web-Cache IP Address", "wccp.web_cache_identity.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3026
16
        NULL, HFILL }
3027
16
    },
3028
16
    { &hf_web_cache_identity_ipv6,
3029
16
      { "Web-Cache IP Address", "wccp.web_cache_identity.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3030
16
        NULL, HFILL }
3031
16
    },
3032
16
    { &hf_web_cache_identity_hash_rev,
3033
16
      { "Hash Revision", "wccp.web_cache_identity.hash_rev", FT_UINT16, BASE_DEC, NULL, 0x0,
3034
16
        NULL, HFILL }
3035
16
    },
3036
16
    { &hf_web_cache_identity_flags,
3037
16
      { "Flags", "wccp.web_cache_identity.flags", FT_UINT16, BASE_HEX, NULL, 0x0,
3038
16
        NULL, HFILL }
3039
16
    },
3040
16
    { &hf_web_cache_identity_flag_hash_info,
3041
16
      { "Hash information", "wccp.web_cache_identity.flags.hash_info", FT_BOOLEAN, 16,
3042
16
        TFS(&tfs_historical_current), 0x1,
3043
16
        NULL, HFILL }
3044
16
    },
3045
16
    { &hf_web_cache_identity_flag_assign_type,
3046
16
      { "Assignment Type", "wccp.web_cache_identity.flags.assign_type", FT_UINT16, BASE_HEX,
3047
16
        VALS(wccp_web_cache_assignment_data_type_val), 0x6,
3048
16
        NULL, HFILL }
3049
16
    },
3050
16
    { &hf_web_cache_identity_flag_version_request,
3051
16
      { "Version Request", "wccp.web_cache_identity.flags.version_request", FT_BOOLEAN, 16,
3052
16
        TFS(&tfs_version_min_max), 0x8,
3053
16
        NULL, HFILL }
3054
16
    },
3055
16
    { &hf_web_cache_identity_flag_reserved,
3056
16
      { "Reserved, should be 0", "wccp.web_cache_identity.flags.reserved", FT_UINT16, BASE_HEX,
3057
16
        NULL, 0xFFF0,
3058
16
        NULL, HFILL }
3059
16
    },
3060
16
    { &hf_mask_value_set_element_value_element_num,
3061
16
      { "Number of Value Elements", "wccp.mask_value_set_element.value_element_num", FT_UINT32, BASE_DEC, 0x0, 0x0,
3062
16
        NULL, HFILL }
3063
16
    },
3064
16
    { &hf_assignment_weight,
3065
16
      { "Assignment Weight", "wccp.assignment_weight", FT_UINT16, BASE_DEC, NULL, 0x0,
3066
16
        NULL, HFILL }
3067
16
    },
3068
16
    { &hf_assignment_status,
3069
16
      { "Status", "wccp.assignment_status", FT_UINT16, BASE_HEX, NULL, 0x0,
3070
16
        NULL, HFILL }
3071
16
    },
3072
16
    { &hf_assignment_key_ip_index,
3073
16
      { "Assignment Key IP Address", "wccp.assignment_key.ip_index", FT_UINT32, BASE_DEC, NULL, 0x0,
3074
16
        NULL, HFILL }
3075
16
    },
3076
16
    { &hf_assignment_key_ipv4,
3077
16
      { "Assignment Key IP Address", "wccp.assignment_key.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3078
16
        NULL, HFILL }
3079
16
    },
3080
16
    { &hf_assignment_key_ipv6,
3081
16
      { "Assignment Key IP Address", "wccp.assignment_key.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3082
16
        NULL, HFILL }
3083
16
    },
3084
16
    { &hf_assignment_key_change_num,
3085
16
      { "Assignment Key Change Number", "wccp.assignment_key.change_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3086
16
        NULL, HFILL }
3087
16
    },
3088
16
    { &hf_assignment_no_data,
3089
16
      { "No Assignment Data Present", "wccp.assignment_no_data", FT_NONE, BASE_NONE, NULL, 0x0,
3090
16
        NULL, HFILL }
3091
16
    },
3092
16
    { &hf_router_view_member_change_num,
3093
16
      { "Member Change Number", "wccp.router_view.member_change_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3094
16
        NULL, HFILL }
3095
16
    },
3096
16
    { &hf_router_router_num,
3097
16
      { "Number of Routers", "wccp.router_view.router_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3098
16
        NULL, HFILL }
3099
16
    },
3100
16
    { &hf_router_identity_router_ip_index,
3101
16
      { "Router IP Address", "wccp.router_identity.router_ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3102
16
        NULL, HFILL }
3103
16
    },
3104
16
    { &hf_router_identity_router_ipv4,
3105
16
      { "Router IP Address", "wccp.router_identity.router_ip.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3106
16
        NULL, HFILL }
3107
16
    },
3108
16
    { &hf_router_identity_router_ipv6,
3109
16
      { "Router IP Address", "wccp.router_identity.router_ip.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3110
16
        NULL, HFILL }
3111
16
    },
3112
16
    { &hf_router_identity_received_from_ip_index,
3113
16
      { "Received From IP Address/Target Web Cache IP", "wccp.router_identity.received_from_ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3114
16
        NULL, HFILL }
3115
16
    },
3116
16
    { &hf_router_identity_received_from_ipv4,
3117
16
      { "Received From IP Address/Target Web Cache IP", "wccp.router_identity.received_from_ip.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3118
16
        NULL, HFILL }
3119
16
    },
3120
16
    { &hf_router_identity_received_from_ipv6,
3121
16
      { "Received From IP Address/Target Web Cache IP", "wccp.router_identity.received_from_ip.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3122
16
        NULL, HFILL }
3123
16
    },
3124
16
    { &hf_wc_view_info_change_num,
3125
16
      { "Change Number", "wccp.wc_view_info.change_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3126
16
        NULL, HFILL }
3127
16
    },
3128
16
    { &hf_wc_view_info_router_ip_index,
3129
16
      { "Router IP", "wccp.wc_view_info.router_ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3130
16
        NULL, HFILL }
3131
16
    },
3132
16
    { &hf_wc_view_info_router_ipv4,
3133
16
      { "Router IP", "wccp.wc_view_info.router_ip.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3134
16
        NULL, HFILL }
3135
16
    },
3136
16
    { &hf_wc_view_info_router_ipv6,
3137
16
      { "Router IP", "wccp.wc_view_info.router_ip.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3138
16
        NULL, HFILL }
3139
16
    },
3140
16
    { &hf_wc_view_info_wc_ip_index,
3141
16
      { "Web Cache IP", "wccp.wc_view_info.wc_ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3142
16
        NULL, HFILL }
3143
16
    },
3144
16
    { &hf_wc_view_info_wc_ipv4,
3145
16
      { "Web Cache IP", "wccp.wc_view_info.wc_ip.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3146
16
        NULL, HFILL }
3147
16
    },
3148
16
    { &hf_wc_view_info_wc_ipv6,
3149
16
      { "Web Cache IP", "wccp.wc_view_info.wc_ip.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3150
16
        NULL, HFILL }
3151
16
    },
3152
16
    { &hf_wc_view_router_num,
3153
16
      { "Number of Routers", "wccp.wc_view_info.router_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3154
16
        NULL, HFILL }
3155
16
    },
3156
16
    { &hf_wc_view_wc_num,
3157
16
      { "Number of Web Caches", "wccp.wc_view_info.wc_num", FT_UINT32, BASE_DEC, 0x0, 0x0,
3158
16
        NULL, HFILL }
3159
16
    },
3160
16
    { &hf_wc_identity_ip_address_index,
3161
16
      { "Web Cache Identity", "wccp.wc_identity_ip_address.index", FT_UINT32, BASE_DEC, NULL, 0x0,
3162
16
        "The IP identifying the Web Cache", HFILL }
3163
16
    },
3164
16
    { &hf_wc_identity_ip_address_ipv4,
3165
16
      { "Web Cache Identity", "wccp.wc_identity_ip_address.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3166
16
        "The IP identifying the Web Cache", HFILL }
3167
16
    },
3168
16
    { &hf_wc_identity_ip_address_ipv6,
3169
16
      { "Web Cache Identity", "wccp.wc_identity_ip_address.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3170
16
        "The IP identifying the Web Cache", HFILL }
3171
16
    },
3172
16
    { &hf_router_assignment_element_change_num,
3173
16
      { "Change Number", "wccp.router_assignment_element.change_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3174
16
        NULL, HFILL }
3175
16
    },
3176
16
    { &hf_assignment_info_router_num,
3177
16
      { "Number of Routers", "wccp.assignment_info.router_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3178
16
        NULL, HFILL }
3179
16
    },
3180
16
    { &hf_assignment_info_router_ip_index,
3181
16
      { "Router IP", "wccp.assignment_info.router_ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3182
16
        NULL, HFILL }
3183
16
    },
3184
16
    { &hf_assignment_info_router_ipv4,
3185
16
      { "Router IP", "wccp.assignment_info.router_ip.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3186
16
        NULL, HFILL }
3187
16
    },
3188
16
    { &hf_assignment_info_router_ipv6,
3189
16
      { "Router IP", "wccp.assignment_info.router_ip.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3190
16
        NULL, HFILL }
3191
16
    },
3192
16
    { &hf_hash_buckets_assignment_wc_num,
3193
16
      { "Number of WC", "wccp.hash_buckets_assignment.wc_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3194
16
        NULL, HFILL }
3195
16
    },
3196
16
    { &hf_hash_buckets_assignment_wc_ip_index,
3197
16
      { "WC IP", "wccp.hash_buckets_assignment.wc_ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3198
16
        NULL, HFILL }
3199
16
    },
3200
16
    { &hf_hash_buckets_assignment_wc_ipv4,
3201
16
      { "WC IP", "wccp.hash_buckets_assignment.wc_ip.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3202
16
        NULL, HFILL }
3203
16
    },
3204
16
    { &hf_hash_buckets_assignment_wc_ipv6,
3205
16
      { "WC IP", "wccp.hash_buckets_assignment.wc_ip.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3206
16
        NULL, HFILL }
3207
16
    },
3208
16
    { &hf_router_view_ip_index,
3209
16
      { "Router IP Address", "wccp.router_view.ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3210
16
        NULL, HFILL }
3211
16
    },
3212
16
    { &hf_router_view_ipv4,
3213
16
      { "Router IP Address", "wccp.router_view.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3214
16
        NULL, HFILL }
3215
16
    },
3216
16
    { &hf_router_view_ipv6,
3217
16
      { "Router IP Address", "wccp.router_view.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3218
16
        NULL, HFILL }
3219
16
    },
3220
16
    { &hf_router_query_info_ip_index,
3221
16
      { "Web-Cache Identity Element IP address", "wccp.router_query_info.ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3222
16
        NULL, HFILL }
3223
16
    },
3224
16
    { &hf_router_query_info_ipv4,
3225
16
      { "Web-Cache Identity Element IP address", "wccp.router_query_info.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3226
16
        NULL, HFILL }
3227
16
    },
3228
16
    { &hf_router_query_info_ipv6,
3229
16
      { "Web-Cache Identity Element IP address", "wccp.router_query_info.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3230
16
        NULL, HFILL }
3231
16
    },
3232
16
    { &hf_router_query_info_send_to_ip_index,
3233
16
      { "Sent To IP Address", "wccp.router_query_info.send_to_ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3234
16
        NULL, HFILL }
3235
16
    },
3236
16
    { &hf_router_query_info_send_to_ipv4,
3237
16
      { "Sent To IP Address", "wccp.router_query_info.send_to_ip.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3238
16
        NULL, HFILL }
3239
16
    },
3240
16
    { &hf_router_query_info_send_to_ipv6,
3241
16
      { "Sent To IP Address", "wccp.router_query_info.send_to_ip.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3242
16
        NULL, HFILL }
3243
16
    },
3244
16
    { &hf_router_query_info_target_ip_index,
3245
16
      { "Target IP Address", "wccp.router_query_info.target_ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3246
16
        NULL, HFILL }
3247
16
    },
3248
16
    { &hf_router_query_info_target_ipv4,
3249
16
      { "Target IP Address", "wccp.router_query_info.target_ip.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3250
16
        NULL, HFILL }
3251
16
    },
3252
16
    { &hf_router_query_info_target_ipv6,
3253
16
      { "Target IP Address", "wccp.router_query_info.target_ip.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3254
16
        NULL, HFILL }
3255
16
    },
3256
16
    { &hf_capability_element_type,
3257
16
      { "Type", "wccp.capability_element.type", FT_UINT16, BASE_DEC, VALS(capability_type_vals), 0x0,
3258
16
        NULL, HFILL }
3259
16
    },
3260
16
    { &hf_capability_element_length,
3261
16
      { "Value Length", "wccp.capability_element.length", FT_UINT16, BASE_DEC, NULL, 0x0,
3262
16
        NULL, HFILL }
3263
16
    },
3264
16
    { &hf_capability_info_value,
3265
16
      { "Value", "wccp.capability_info.value", FT_UINT32, BASE_HEX, NULL, 0x0,
3266
16
        NULL, HFILL }
3267
16
    },
3268
16
    { &hf_capability_forwarding_method_flag_gre,
3269
16
      { "GRE-encapsulated", "wccp.capability_info.forwarding_method_flag.gre", FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), WCCP2_FORWARDING_METHOD_GRE,
3270
16
        NULL, HFILL }
3271
16
    },
3272
16
    { &hf_capability_forwarding_method_flag_l2,
3273
16
      { "L2 rewrite", "wccp.capability_info.forwarding_method_flag.l2", FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), WCCP2_FORWARDING_METHOD_L2,
3274
16
        NULL, HFILL }
3275
16
    },
3276
16
    { &hf_capability_assignment_method_flag_hash,
3277
16
      { "Hash", "wccp.capability_info.assignment_method_flag.hash", FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), WCCP2_ASSIGNMENT_METHOD_HASH,
3278
16
        NULL, HFILL }
3279
16
    },
3280
16
    { &hf_capability_assignment_method_flag_mask,
3281
16
      { "Mask", "wccp.capability_info.assignment_method_flag.mask", FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), WCCP2_ASSIGNMENT_METHOD_MASK,
3282
16
        NULL, HFILL }
3283
16
    },
3284
16
    { &hf_capability_return_method_flag_gre,
3285
16
      { "GRE-encapsulated", "wccp.capability_info.return_method_flag.gre", FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), WCCP2_PACKET_RETURN_METHOD_GRE,
3286
16
        NULL, HFILL }
3287
16
    },
3288
16
    { &hf_capability_return_method_flag_l2,
3289
16
      { "L2 rewrite", "wccp.capability_info.return_method_flag.l2", FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), WCCP2_PACKET_RETURN_METHOD_L2,
3290
16
        NULL, HFILL }
3291
16
    },
3292
16
    { &hf_capability_transmit_t,
3293
16
      { "Message interval in milliseconds", "wccp.capability.transmit_t", FT_UINT16, BASE_DEC, NULL, 0x0,
3294
16
        NULL, HFILL }
3295
16
    },
3296
16
    { &hf_capability_transmit_t_upper_limit,
3297
16
      { "Message interval upper limit in milliseconds", "wccp.capability.transmit_t.upper_limit", FT_UINT16, BASE_DEC, NULL, 0x0,
3298
16
        NULL, HFILL }
3299
16
    },
3300
16
    { &hf_capability_transmit_t_lower_limit,
3301
16
      { "Message interval lower limit in milliseconds", "wccp.capability.transmit_t.lower_limit", FT_UINT16, BASE_DEC, NULL, 0x0,
3302
16
        NULL, HFILL }
3303
16
    },
3304
16
    { &hf_capability_timer_scale_timeout_scale,
3305
16
      { "Timer scale", "wccp.capability.timer_scale.timeout_scale", FT_UINT8, BASE_DEC, NULL, 0x0,
3306
16
        NULL, HFILL }
3307
16
    },
3308
16
    { &hf_capability_timer_scale_timeout_scale_upper_limit,
3309
16
      { "Timer scale upper limit", "wccp.capability.timer_scale.timeout_scale.upper_limit", FT_UINT8, BASE_DEC, NULL, 0x0,
3310
16
        NULL, HFILL }
3311
16
    },
3312
16
    { &hf_capability_timer_scale_timeout_scale_lower_limit,
3313
16
      { "Timer scale lower limit", "wccp.capability.timer_scale.timeout_scale.lower_limit", FT_UINT8, BASE_DEC, NULL, 0x0,
3314
16
        NULL, HFILL }
3315
16
    },
3316
16
    { &hf_capability_timer_scale_ra_timer_scale,
3317
16
      { "RA Timer scale", "wccp.capability.timer_scale.ra_timer_scale", FT_UINT8, BASE_DEC, NULL, 0x0,
3318
16
        NULL, HFILL }
3319
16
    },
3320
16
    { &hf_capability_timer_scale_ra_scale_upper_limit,
3321
16
      { "RA Timer scale upper limit", "wccp.capability.timer_scale.ra_timer_scale.upper_limit", FT_UINT8, BASE_DEC, NULL, 0x0,
3322
16
        NULL, HFILL }
3323
16
    },
3324
16
    { &hf_capability_timer_scale_ra_scale_lower_limit,
3325
16
      { "RA Timer scale lower limit", "wccp.capability.timer_scale.ra_timer_scale.lower_limit", FT_UINT8, BASE_DEC, NULL, 0x0,
3326
16
        NULL, HFILL }
3327
16
    },
3328
16
    { &hf_capability_value,
3329
16
      { "Value", "wccp.capability.value", FT_BYTES, BASE_NONE, NULL, 0x0,
3330
16
        NULL, HFILL }
3331
16
    },
3332
16
    { &hf_reserved_zero,
3333
16
      { "Reserved, must be 0", "wccp.reserved_zero", FT_UINT16, BASE_DEC, NULL, 0x0,
3334
16
        NULL, HFILL }
3335
16
    },
3336
16
    { &hf_value_element_src_ip_index,
3337
16
      { "Source Address", "wccp.value_element.src_ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3338
16
        NULL, HFILL }
3339
16
    },
3340
16
    { &hf_value_element_src_ipv4,
3341
16
      { "Source Address", "wccp.value_element.src_ip.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3342
16
        NULL, HFILL }
3343
16
    },
3344
16
    { &hf_value_element_src_ipv6,
3345
16
      { "Source Address", "wccp.value_element.src_ip.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3346
16
        NULL, HFILL }
3347
16
    },
3348
16
    { &hf_value_element_dest_ip_index,
3349
16
      { "Destination Address", "wccp.value_element.dest_ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3350
16
        NULL, HFILL }
3351
16
    },
3352
16
    { &hf_value_element_dest_ipv4,
3353
16
      { "Destination Address", "wccp.value_element.dest_ip.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3354
16
        NULL, HFILL }
3355
16
    },
3356
16
    { &hf_value_element_dest_ipv6,
3357
16
      { "Destination Address", "wccp.value_element.dest_ip.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3358
16
        NULL, HFILL }
3359
16
    },
3360
16
    { &hf_value_element_src_port,
3361
16
      { "Source Port", "wccp.value_element.src_port", FT_UINT16, BASE_DEC, NULL, 0x0,
3362
16
        NULL, HFILL }
3363
16
    },
3364
16
    { &hf_value_element_dest_port,
3365
16
      { "Destination Port", "wccp.value_element.dest_port", FT_UINT16, BASE_DEC, NULL, 0x0,
3366
16
        NULL, HFILL }
3367
16
    },
3368
16
    { &hf_value_element_web_cache_ip_index,
3369
16
      { "Web Cache Address", "wccp.value_element.web_cache_ip.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3370
16
        NULL, HFILL }
3371
16
    },
3372
16
    { &hf_value_element_web_cache_ipv4,
3373
16
      { "Web Cache Address", "wccp.value_element.web_cache_ip.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3374
16
        NULL, HFILL }
3375
16
    },
3376
16
    { &hf_value_element_web_cache_ipv6,
3377
16
      { "Web Cache Address", "wccp.value_element.web_cache_ip.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3378
16
        NULL, HFILL }
3379
16
    },
3380
16
    { &hf_mask_value_set_list_num_elements,
3381
16
      { "Number of elements", "wccp.mask_value_set_list.num_elements", FT_UINT32, BASE_DEC, NULL, 0x0,
3382
16
        NULL, HFILL }
3383
16
    },
3384
16
    { &hf_mask_element_src_ip,
3385
16
      { "Source Address Mask", "wccp.mask_element.src_ip", FT_UINT32, BASE_HEX, NULL, 0x0,
3386
16
        NULL, HFILL }
3387
16
    },
3388
16
    { &hf_mask_element_dest_ip,
3389
16
      { "Destination Address Mask", "wccp.mask_element.dest_ip", FT_UINT32, BASE_HEX, NULL, 0x0,
3390
16
        NULL, HFILL }
3391
16
    },
3392
16
    { &hf_mask_element_src_port,
3393
16
      { "Source Port Mask", "wccp.mask_element.src_port", FT_UINT16, BASE_HEX, NULL, 0x0,
3394
16
        NULL, HFILL }
3395
16
    },
3396
16
    { &hf_mask_element_dest_port,
3397
16
      { "Destination Port Mask", "wccp.mask_element.dest_port", FT_UINT16, BASE_HEX, NULL, 0x0,
3398
16
        NULL, HFILL }
3399
16
    },
3400
16
    { &hf_alt_assignment_info_assignment_type,
3401
16
      { "Assignment type", "wccp.alt_assignment_info.assignment_type", FT_UINT16, BASE_DEC, VALS(assignment_type_vals), 0x0,
3402
16
        NULL, HFILL }
3403
16
    },
3404
16
    { &hf_extended_assignment_data_type,
3405
16
      { "Assignment type", "wccp.extended_assignment_data.type", FT_UINT16, BASE_DEC, VALS(assignment_type_vals), 0x0,
3406
16
        NULL, HFILL }
3407
16
    },
3408
16
    { &hf_alt_assignment_map_assignment_type,
3409
16
      { "Assignment type", "wccp.alt_assignment_map.assignment_type", FT_UINT16, BASE_DEC, VALS(assignment_type_vals), 0x0,
3410
16
        NULL, HFILL }
3411
16
    },
3412
16
    { &hf_alt_assignment_map_assignment_length,
3413
16
      { "Assignment length", "wccp.alt_assignment_map.assignment_length", FT_UINT16, BASE_DEC, NULL, 0x0,
3414
16
        NULL, HFILL }
3415
16
    },
3416
16
    { &hf_alt_assignment_info_assignment_length,
3417
16
      { "Assignment length", "wccp.alt_assignment_info.assignment_length", FT_UINT16, BASE_DEC, NULL, 0x0,
3418
16
        NULL, HFILL }
3419
16
    },
3420
16
    { &hf_extended_assignment_data_length,
3421
16
      { "Assignment length", "wccp.extended_assignment_data.length", FT_UINT16, BASE_DEC, NULL, 0x0,
3422
16
        NULL, HFILL }
3423
16
    },
3424
16
    { &hf_alt_assignment_info_num_routers,
3425
16
      { "Number of routers", "wccp.alt_assignment_info.num_routers", FT_UINT32, BASE_DEC, NULL, 0x0,
3426
16
        NULL, HFILL }
3427
16
    },
3428
16
    { &hf_alt_assignment_mask_value_set_element_num_wc_value_elements,
3429
16
      { "Number of Web-Cache Value Elements", "wccp.alt_assignment_mask_value_set_element.num_wc_value_elements", FT_UINT32, BASE_DEC, NULL, 0x0,
3430
16
        NULL, HFILL }
3431
16
    },
3432
16
    { &hf_web_cache_value_element_wc_address_index,
3433
16
      { "Web-Cache Address", "wccp.web_cache_value_element.wc_address.index", FT_UINT32, BASE_HEX, NULL, 0x0,
3434
16
        NULL, HFILL }
3435
16
    },
3436
16
    { &hf_web_cache_value_element_wc_address_ipv4,
3437
16
      { "Web-Cache Address", "wccp.web_cache_value_element.wc_address.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
3438
16
        NULL, HFILL }
3439
16
    },
3440
16
    { &hf_web_cache_value_element_wc_address_ipv6,
3441
16
      { "Web-Cache Address", "wccp.web_cache_value_element.wc_address.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
3442
16
        NULL, HFILL }
3443
16
    },
3444
16
    { &hf_web_cache_value_element_num_values,
3445
16
      { "Number of Value Sequence Numbers", "wccp.web_cache_value_element.num_values", FT_UINT32, BASE_DEC, NULL, 0x0,
3446
16
        NULL, HFILL }
3447
16
    },
3448
16
    { &hf_web_cache_value_seq_num,
3449
16
      { "Value Sequence Number", "wccp.web_cache_value_element.value_seq_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3450
16
        NULL, HFILL }
3451
16
    },
3452
16
    { &hf_alt_assignment_mask_value_set_list_num_elements,
3453
16
      { "Number of Alternate Mask/Value Set Elements", "wccp.alt_assignment_mask_value_list.num_elements", FT_UINT32, BASE_DEC, NULL, 0x0,
3454
16
        NULL, HFILL }
3455
16
    },
3456
16
    { &hf_address_table_family,
3457
16
      { "Family Type", "wccp.address_table.family_type", FT_UINT16, BASE_DEC, VALS(wccp_address_family_val), 0x0,
3458
16
        "The WCCP Address Table Family type", HFILL }
3459
16
    },
3460
16
    { &hf_address_table_address_length,
3461
16
      { "Address Length", "wccp.address_table.address_length", FT_UINT16, BASE_DEC, NULL, 0x0,
3462
16
        "The WCCP Address Table Address Length", HFILL }
3463
16
    },
3464
16
    { &hf_address_table_length,
3465
16
      { "Length", "wccp.address_table.length", FT_UINT32, BASE_DEC, NULL, 0x0,
3466
16
        "The WCCP Address Table Length", HFILL }
3467
16
    },
3468
16
    { &hf_address_table_element,
3469
16
      { "Address", "wccp.address_table.element", FT_STRING, BASE_NONE, NULL, 0x0,
3470
16
        NULL, HFILL }
3471
16
    },
3472
3473
16
  };
3474
16
  static int *ett[] = {
3475
16
    &ett_wccp,
3476
16
    &ett_buckets,
3477
16
    &ett_hash_assignment_buckets,
3478
16
    &ett_mask_assignment_data_element,
3479
16
    &ett_alternate_mask_assignment_data_element,
3480
16
    &ett_extended_assigment_data_element,
3481
16
    &ett_table_element,
3482
16
    &ett_hash_flags,
3483
16
    &ett_wc_identity_flags,
3484
16
    &ett_cache_info,
3485
16
    &ett_security_info,
3486
16
    &ett_service_info,
3487
16
    &ett_service_flags,
3488
16
    &ett_service_info_ports,
3489
16
    &ett_wc_view_info_router_element,
3490
16
    &ett_router_identity_info,
3491
16
    &ett_wc_identity_element,
3492
16
    &ett_wc_identity_info,
3493
16
    &ett_router_view_info,
3494
16
    &ett_wc_view_info,
3495
16
    &ett_router_assignment_element,
3496
16
    &ett_hash_buckets_assignment_wc_element,
3497
16
    &ett_hash_buckets_assignment_buckets,
3498
16
    &ett_router_alt_assignment_element,
3499
16
    &ett_router_assignment_info,
3500
16
    &ett_query_info,
3501
16
    &ett_capabilities_info,
3502
16
    &ett_capability_element,
3503
16
    &ett_capability_forwarding_method,
3504
16
    &ett_capability_assignment_method,
3505
16
    &ett_capability_return_method,
3506
16
    &ett_capability_transmit_t,
3507
16
    &ett_capability_timer_scale,
3508
16
    &ett_alt_assignment_info,
3509
16
    &ett_alt_assignment_map,
3510
16
    &ett_address_table,
3511
16
    &ett_assignment_map,
3512
16
    &ett_command_extension,
3513
16
    &ett_alternate_mask_value_set,
3514
16
    &ett_alternate_mask_value_set_element,
3515
16
    &ett_mv_set_list,
3516
16
    &ett_mv_set_element,
3517
16
    &ett_mv_set_value_list,
3518
16
    &ett_alternate_mv_set_element_list,
3519
16
    &ett_web_cache_value_element_list,
3520
16
    &ett_alternate_mv_set_element,
3521
16
    &ett_value_element,
3522
16
    &ett_unknown_info,
3523
16
  };
3524
3525
16
  static ei_register_info ei[] = {
3526
16
     { &ei_wccp_missing_security_info, { "wccp.missing.security_info", PI_PROTOCOL, PI_ERROR, "This message should contain a Security Info component, but it is missing", EXPFILL }},
3527
16
     { &ei_wccp_missing_service_info, { "wccp.missing.service_info", PI_PROTOCOL, PI_ERROR, "This message should contain a Service Info component, but it is missing", EXPFILL }},
3528
16
     { &ei_wccp_missing_wc_id_info, { "wccp.missing.wc_id_info", PI_PROTOCOL, PI_ERROR, "This message should contain a Web-Cache Identity Info component, but it is missing", EXPFILL }},
3529
16
     { &ei_wccp_missing_router_id_info, { "wccp.missing.router_id_info", PI_PROTOCOL, PI_ERROR, "This message should contain a Router Identity Info component, but it is missing", EXPFILL }},
3530
16
     { &ei_wccp_missing_query_info, { "wccp.missing.query_info", PI_PROTOCOL, PI_ERROR, "This message should contain a Query Info component, but it is missing", EXPFILL }},
3531
16
     { &ei_wccp_missing_wc_view_info, { "wccp.missing.wc_view_info", PI_PROTOCOL, PI_ERROR, "This message should contain a Web-Cache View Info component, but it is missing", EXPFILL }},
3532
16
     { &ei_wccp_missing_rtr_view_info, { "wccp.missing.rtr_view_info", PI_PROTOCOL, PI_ERROR, "This message should contain a Router View Info component, but it is missing", EXPFILL }},
3533
16
     { &ei_wccp_missing_assignment, { "wccp.missing.assignment", PI_PROTOCOL, PI_ERROR, "This message should contain a Alternate Assignment, Assignment Map, Assignment Info or "
3534
16
                                      "Alternative Assignment Map component, but it is missing", EXPFILL }},
3535
16
     { &ei_wccp_contains_redirect_assignment, { "wccp.contains.redirect_assignment", PI_PROTOCOL, PI_ERROR, "This message contains a Assignment Info component, but it should not", EXPFILL }},
3536
16
     { &ei_wccp_contains_router_id_info, { "wccp.contains.router_id_info", PI_PROTOCOL, PI_ERROR, "This message contains a Router Identity Info component, but it should not", EXPFILL }},
3537
16
     { &ei_wccp_contains_rtr_view_info, { "wccp.contains.rtr_view_info", PI_PROTOCOL, PI_ERROR, "This message contains a Router View Info component, but it should not", EXPFILL }},
3538
16
     { &ei_wccp_contains_query_info, { "wccp.contains.query_info", PI_PROTOCOL, PI_ERROR, "This message contains a Query Info component, but it should not", EXPFILL }},
3539
16
     { &ei_wccp_contains_alt_assignment, { "wccp.contains.alt_assignment", PI_PROTOCOL, PI_ERROR, "This message contains a Alternate Assignment component, but it should not", EXPFILL }},
3540
16
     { &ei_wccp_contains_assign_map, { "wccp.contains.assign_map", PI_PROTOCOL, PI_ERROR, "This message contains a Assignment Map component, but it should not", EXPFILL }},
3541
16
     { &ei_wccp_contains_alt_assignment_map, { "wccp.contains.alt_assignment_map", PI_PROTOCOL, PI_ERROR, "This message contains a Alternative Assignment Map component, but it should not", EXPFILL }},
3542
16
     { &ei_wccp_contains_wc_id_info, { "wccp.contains.wc_id_info", PI_PROTOCOL, PI_ERROR, "This message contains a Web-Cache Identity Info component, but it should not", EXPFILL }},
3543
16
     { &ei_wccp_contains_wc_view_info, { "wccp.contains.wc_view_info", PI_PROTOCOL, PI_ERROR, "This message contains a Web-Cache View Info component, but it should not", EXPFILL }},
3544
16
     { &ei_wccp_contains_capabilities_info, { "wccp.contains.capabilities_info", PI_PROTOCOL, PI_ERROR, "This message contains a Capabilities Info component, but it should not", EXPFILL }},
3545
16
     { &ei_wccp_contains_command_extension, { "wccp.contains.command_extension", PI_PROTOCOL, PI_ERROR, "This message contains a Command Extension component, but it should not", EXPFILL }},
3546
16
     { &ei_wccp_assignment_length_bad, { "wccp.assignment_length_bad", PI_PROTOCOL, PI_ERROR, "Assignment length bad", EXPFILL }},
3547
16
     { &ei_wccp_length_bad, { "wccp.length_bad", PI_PROTOCOL, PI_ERROR, "Length bad", EXPFILL }},
3548
16
     { &ei_wccp_service_info_priority_nonzero, { "wccp.service_info_priority.nonzero", PI_PROTOCOL, PI_WARN, "The priority must be zero for well-known services.", EXPFILL }},
3549
16
     { &ei_wccp_service_info_protocol_nonzero, { "wccp.service_info_protocol.nonzero", PI_PROTOCOL, PI_WARN, "The protocol must be zero for well-known services.", EXPFILL }},
3550
16
     { &ei_wccp_router_identity_receive_id_zero, { "wccp.router_identity.receive_id.zero", PI_PROTOCOL, PI_WARN, "Receive ID shouldn't be 0", EXPFILL }},
3551
16
     { &ei_wccp_web_cache_identity_hash_rev_zero, { "wccp.web_cache_identity.hash_rev.zero", PI_PROTOCOL, PI_WARN, "Should be 0 (6.4)", EXPFILL }},
3552
16
     { &ei_wccp_address_table_family_unknown, { "wccp.address_table.family_type.unknown", PI_PROTOCOL, PI_ERROR, "Unknown address family", EXPFILL }},
3553
16
     { &ei_wccp_capability_element_length, { "wccp.capability_element.length.invalid", PI_PROTOCOL, PI_WARN, "Value Length invalid", EXPFILL }},
3554
16
     { &ei_wccp_port_fields_not_used, { "wccp.port_fields_not_used", PI_PROTOCOL, PI_NOTE, "Ports fields not used", EXPFILL }},
3555
16
     { &ei_wccp_a_zero_not_c, { "wccp.a_zero_not_c", PI_PROTOCOL, PI_WARN, "Error A is 0, but C is not", EXPFILL }},
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
16
  };
3560
3561
16
  expert_module_t* expert_wccp;
3562
3563
16
  proto_wccp = proto_register_protocol("Web Cache Communication Protocol",
3564
16
                                       "WCCP", "wccp");
3565
16
  proto_register_field_array(proto_wccp, hf, array_length(hf));
3566
16
  proto_register_subtree_array(ett, array_length(ett));
3567
16
  expert_wccp = expert_register_protocol(proto_wccp);
3568
16
  expert_register_field_array(expert_wccp, ei, array_length(ei));
3569
16
  wccp_handle = register_dissector("wccp", dissect_wccp, proto_wccp);
3570
16
}
3571
3572
void
3573
proto_reg_handoff_wccp(void)
3574
16
{
3575
16
  dissector_add_uint_with_preference("udp.port", UDP_PORT_WCCP, wccp_handle);
3576
16
}
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
 */