2 * Routines for Performace Co-Pilot protocol dissection
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0-or-later
13 #include <epan/packet.h>
14 #include <epan/expert.h>
16 #include <wsutil/array.h>
17 #include "packet-tcp.h"
18 #include "packet-tls-utils.h"
20 void proto_register_pcp(void);
21 void proto_reg_handoff_pcp(void);
23 #define PCP_PORT 44321
24 #define PMPROXY_PORT 44322
25 #define PCP_HEADER_LEN 12
27 #define PM_ERR_NAME -12357
29 static dissector_handle_t pcp_handle
;
32 static int hf_pcp_pdu_length
;
33 static int hf_pcp_pdu_type
;
34 static int hf_pcp_pdu_pid
;
35 static int hf_pcp_pdu_error
;
36 static int hf_pcp_pdu_padding
;
37 static int hf_pcp_creds_number_of
;
38 static int hf_pcp_creds_type
;
39 static int hf_pcp_creds_version
;
40 static int hf_pcp_start
;
41 static int hf_pcp_start_status
;
42 static int hf_pcp_start_zero
;
43 static int hf_pcp_start_version
;
44 static int hf_pcp_start_licensed
;
45 static int hf_pcp_features_flags
;
46 static int hf_pcp_features_flags_secure
;
47 static int hf_pcp_features_flags_compress
;
48 static int hf_pcp_features_flags_auth
;
49 static int hf_pcp_features_flags_creds_reqd
;
50 static int hf_pcp_features_flags_secure_ack
;
51 static int hf_pcp_features_flags_no_nss_init
;
52 static int hf_pcp_features_flags_container
;
53 static int hf_pcp_features_flags_cert_reqd
;
54 static int hf_pcp_features_flags_bad_label
;
55 static int hf_pcp_features_flags_labels
;
56 static int hf_pcp_pmns_traverse
;
57 static int hf_pcp_pmns_subtype
;
58 static int hf_pcp_pmns_namelen
;
59 static int hf_pcp_pmns_name
;
60 static int hf_pcp_pmns_names
;
61 static int hf_pcp_pmns_names_nstrbytes
;
62 static int hf_pcp_pmns_names_numstatus
;
63 static int hf_pcp_pmns_names_numnames
;
64 static int hf_pcp_pmns_names_nametree
;
65 static int hf_pcp_pmns_names_nametree_status
;
66 static int hf_pcp_pmns_names_nametree_namelen
;
67 static int hf_pcp_pmns_names_nametree_name
;
68 static int hf_pcp_pmns_ids
;
69 static int hf_pcp_pmns_ids_status
;
70 static int hf_pcp_pmns_ids_numids
;
71 static int hf_pcp_pmns_child
;
72 static int hf_pcp_pmid
;
73 static int hf_pcp_pmid_flag
;
74 static int hf_pcp_pmid_domain
;
75 static int hf_pcp_pmid_cluster
;
76 static int hf_pcp_pmid_item
;
77 static int hf_pcp_pmid_type
;
78 static int hf_pcp_pmid_sem
;
79 static int hf_pcp_pmid_inst
;
80 static int hf_pcp_profile
;
81 static int hf_pcp_ctxnum
;
82 static int hf_pcp_profile_g_state
;
83 static int hf_pcp_profile_numprof
;
84 static int hf_pcp_profile_profile
;
85 static int hf_pcp_profile_profile_state
;
86 static int hf_pcp_profile_profile_numinst
;
87 static int hf_pcp_fetch
;
88 static int hf_pcp_fetch_numpmid
;
89 static int hf_pcp_when
;
90 static int hf_pcp_when_sec
;
91 static int hf_pcp_when_usec
;
92 static int hf_pcp_desc
;
93 static int hf_pcp_desc_req
;
94 static int hf_pcp_units
;
95 static int hf_pcp_units_dimspace
;
96 static int hf_pcp_units_dimtime
;
97 static int hf_pcp_units_dimcount
;
98 static int hf_pcp_units_scalespace
;
99 static int hf_pcp_units_scaletime
;
100 static int hf_pcp_units_scalecount
;
101 static int hf_pcp_instance
;
102 static int hf_pcp_instance_req
;
103 static int hf_pcp_instance_namelen
;
104 static int hf_pcp_instance_name
;
105 static int hf_pcp_instance_indom
;
106 static int hf_pcp_instance_valoffset
;
107 static int hf_pcp_instance_vallength
;
108 static int hf_pcp_instance_value_insitu
;
109 static int hf_pcp_instance_value_ptr
;
110 static int hf_pcp_instance_value_int
;
111 static int hf_pcp_instance_value_uint
;
112 static int hf_pcp_instance_value_int64
;
113 static int hf_pcp_instance_value_uint64
;
114 static int hf_pcp_instance_value_float
;
115 static int hf_pcp_instance_value_double
;
116 static int hf_pcp_instance_value_aggr
;
117 static int hf_pcp_instances
;
118 static int hf_pcp_instances_numinst
;
119 static int hf_pcp_results
;
120 static int hf_pcp_results_numpmid
;
121 static int hf_pcp_result
;
122 static int hf_pcp_result_numval
;
123 static int hf_pcp_result_valfmt
;
124 static int hf_pcp_text_req
;
125 static int hf_pcp_text_type
;
126 static int hf_pcp_text_type_format
;
127 static int hf_pcp_text_type_ident
;
128 static int hf_pcp_text
;
129 static int hf_pcp_text_ident
;
130 static int hf_pcp_text_buflen
;
131 static int hf_pcp_text_buffer
;
132 static int hf_pcp_user_auth_payload
;
133 static int hf_pcp_label_req
;
134 static int hf_pcp_label
;
135 static int hf_pcp_label_ident
;
136 static int hf_pcp_label_type
;
137 static int hf_pcp_label_padding
;
138 static int hf_pcp_label_nsets
;
139 static int hf_pcp_label_sets
;
140 static int hf_pcp_label_sets_inst
;
141 static int hf_pcp_label_sets_nlabels
;
142 static int hf_pcp_label_sets_json
;
143 static int hf_pcp_label_sets_jsonlen
;
144 static int hf_pcp_label_sets_labels
;
145 static int hf_pcp_label_sets_labels_nameoffset
;
146 static int hf_pcp_label_sets_labels_namelen
;
147 static int hf_pcp_label_sets_labels_flags
;
148 static int hf_pcp_label_sets_labels_valueoffset
;
149 static int hf_pcp_label_sets_labels_valuelen
;
150 static int hf_pcp_label_sets_labels_name
;
151 static int hf_pcp_label_sets_labels_value
;
154 static int ett_pcp_pdu_length
;
155 static int ett_pcp_pdu_type
;
156 static int ett_pcp_pdu_pid
;
157 static int ett_pcp_pdu_error
;
158 static int ett_pcp_pdu_padding
;
159 static int ett_pcp_creds_number_of
;
160 static int ett_pcp_creds_type
;
161 static int ett_pcp_creds_vala
;
162 static int ett_pcp_creds_valb
;
163 static int ett_pcp_creds_valc
;
164 static int ett_pcp_start
;
165 static int ett_pcp_start_status
;
166 static int ett_pcp_start_zero
;
167 static int ett_pcp_start_version
;
168 static int ett_pcp_start_licensed
;
169 static int ett_pcp_start_features
;
170 static int ett_pcp_pmns_traverse
;
171 static int ett_pcp_pmns_subtype
;
172 static int ett_pcp_pmns_namelen
;
173 static int ett_pcp_pmns_name
;
174 static int ett_pcp_pmns_names
;
175 static int ett_pcp_pmns_names_nstrbytes
;
176 static int ett_pcp_pmns_names_numstatus
;
177 static int ett_pcp_pmns_names_numnames
;
178 static int ett_pcp_pmns_names_nametree
;
179 static int ett_pcp_pmns_names_nametree_status
;
180 static int ett_pcp_pmns_names_nametree_namelen
;
181 static int ett_pcp_pmns_names_nametree_name
;
182 static int ett_pcp_pmns_ids
;
183 static int ett_pcp_pmns_ids_status
;
184 static int ett_pcp_pmns_ids_numids
;
185 static int ett_pcp_pmns_child
;
186 static int ett_pcp_pmid
;
187 static int ett_pcp_pmid_flag
;
188 static int ett_pcp_pmid_domain
;
189 static int ett_pcp_pmid_cluster
;
190 static int ett_pcp_pmid_item
;
191 static int ett_pcp_pmid_type
;
192 static int ett_pcp_pmid_sem
;
193 static int ett_pcp_profile
;
194 static int ett_pcp_ctxnum
;
195 static int ett_pcp_profile_g_state
;
196 static int ett_pcp_profile_numprof
;
197 static int ett_pcp_profile_profile
;
198 static int ett_pcp_profile_profile_state
;
199 static int ett_pcp_profile_profile_numinst
;
200 static int ett_pcp_fetch
;
201 static int ett_pcp_fetch_numpmid
;
202 static int ett_pcp_when
;
203 static int ett_pcp_when_sec
;
204 static int ett_pcp_when_usec
;
205 static int ett_pcp_desc_req
;
206 static int ett_pcp_units
;
207 static int ett_pcp_units_dimspace
;
208 static int ett_pcp_units_dimtime
;
209 static int ett_pcp_units_dimcount
;
210 static int ett_pcp_units_scalespace
;
211 static int ett_pcp_units_scaletime
;
212 static int ett_pcp_units_scalecount
;
213 static int ett_pcp_instance
;
214 static int ett_pcp_instance_req
;
215 static int ett_pcp_instance_namelen
;
216 static int ett_pcp_instance_name
;
217 static int ett_pcp_instance_inst
;
218 static int ett_pcp_instance_indom
;
219 static int ett_pcp_instance_valoffset
;
220 static int ett_pcp_instance_vallength
;
221 static int ett_pcp_instance_value_insitu
;
222 static int ett_pcp_instance_value_ptr
;
223 static int ett_pcp_instance_value_int
;
224 static int ett_pcp_instance_value_uint
;
225 static int ett_pcp_instance_value_int64
;
226 static int ett_pcp_instance_value_uint64
;
227 static int ett_pcp_instance_value_float
;
228 static int ett_pcp_instance_value_double
;
229 static int ett_pcp_instance_value_aggr
;
230 static int ett_pcp_instances
;
231 static int ett_pcp_instances_numinst
;
232 static int ett_pcp_results
;
233 static int ett_pcp_results_numpmid
;
234 static int ett_pcp_result
;
235 static int ett_pcp_result_numval
;
236 static int ett_pcp_result_valfmt
;
237 static int ett_pcp_text_req
;
238 static int ett_pcp_text_type
;
239 static int ett_pcp_text_type_format
;
240 static int ett_pcp_text_type_ident
;
241 static int ett_pcp_text
;
242 static int ett_pcp_text_ident
;
243 static int ett_pcp_text_buflen
;
244 static int ett_pcp_text_buffer
;
246 static expert_field ei_pcp_type_event_unimplemented
;
247 static expert_field ei_pcp_type_nosupport_unsupported
;
248 static expert_field ei_pcp_type_unknown_unknown_value
;
249 static expert_field ei_pcp_unimplemented_value
;
250 static expert_field ei_pcp_unimplemented_packet_type
;
251 static expert_field ei_pcp_ssl_upgrade
;
252 static expert_field ei_pcp_ssl_upgrade_failed
;
253 static expert_field ei_pcp_label_error
;
254 static expert_field ei_pcp_label_error_endianness
;
257 #define PCP_SECURE_ACK_SUCCESSFUL 0
259 static const value_string pcp_feature_flags
[] = {
260 #define PCP_PDU_FLAG_SECURE 0x0001
261 { PCP_PDU_FLAG_SECURE
, "SECURE" },
262 #define PCP_PDU_FLAG_COMPRESS 0x0002
263 { PCP_PDU_FLAG_COMPRESS
, "COMPRESS" },
264 #define PCP_PDU_FLAG_AUTH 0x0004
265 { PCP_PDU_FLAG_AUTH
, "AUTH"},
266 #define PCP_PDU_FLAG_CREDS_REQD 0x0008
267 { PCP_PDU_FLAG_CREDS_REQD
, "CREDS_REQD" },
268 #define PCP_PDU_FLAG_SECURE_ACK 0x0010
269 { PCP_PDU_FLAG_SECURE_ACK
, "SECURE_ACK" },
270 #define PCP_PDU_FLAG_NO_NSS_INIT 0x0020
271 { PCP_PDU_FLAG_NO_NSS_INIT
, "NO_NSS_INIT" },
272 #define PCP_PDU_FLAG_CONTAINER 0x0040
273 { PCP_PDU_FLAG_CONTAINER
, "CONTAINER" },
274 #define PCP_PDU_FLAG_CERT_REQD 0x0080
275 { PCP_PDU_FLAG_CERT_REQD
, "CERT_REQD" },
276 #define PCP_PDU_FLAG_BAD_LABEL 0x0100
277 { PCP_PDU_FLAG_BAD_LABEL
, "BAD_LABEL" },
278 #define PCP_PDU_FLAG_LABELS 0x0200
279 { PCP_PDU_FLAG_LABELS
, "LABELS" },
284 static const value_string packettypenames
[] = {
285 #define PCP_PDU_START_OR_ERROR 0x7000
286 {PCP_PDU_START_OR_ERROR
, "START/ERROR" },
287 #define PCP_PDU_RESULT 0x7001
288 {PCP_PDU_RESULT
, "RESULT" },
289 #define PCP_PDU_PROFILE 0x7002
290 {PCP_PDU_PROFILE
, "PROFILE"},
291 #define PCP_PDU_FETCH 0x7003
292 {PCP_PDU_FETCH
, "FETCH"},
293 #define PCP_PDU_DESC_REQ 0x7004
294 {PCP_PDU_DESC_REQ
, "DESC_REQ"},
295 #define PCP_PDU_DESC 0x7005
296 {PCP_PDU_DESC
, "DESC"},
297 #define PCP_PDU_INSTANCE_REQ 0x7006
298 {PCP_PDU_INSTANCE_REQ
, "INSTANCE_REQ" },
299 #define PCP_PDU_INSTANCE 0x7007
300 {PCP_PDU_INSTANCE
, "INSTANCE" },
301 #define PCP_PDU_TEXT_REQ 0x7008
302 {PCP_PDU_TEXT_REQ
, "TEXT_REQ" },
303 #define PCP_PDU_TEXT 0x7009
304 {PCP_PDU_TEXT
, "TEXT" },
305 #define PCP_PDU_CONTROL_REQ 0x700a
306 {PCP_PDU_CONTROL_REQ
, "CONTROL_REQ" }, /* unimplemented (pmlc/pmlogger only) */
307 #define PCP_PDU_DATA_X 0x700b
308 {PCP_PDU_DATA_X
, "DATA_X" }, /* unimplemented (pmlc/pmlogger only) */
309 #define PCP_PDU_CREDS 0x700c
310 {PCP_PDU_CREDS
, "CREDS" },
311 #define PCP_PDU_PMNS_IDS 0x700d
312 {PCP_PDU_PMNS_IDS
, "PMNS_IDS" },
313 #define PCP_PDU_PMNS_NAMES 0x700e
314 {PCP_PDU_PMNS_NAMES
, "PMNS_NAMES" },
315 #define PCP_PDU_PMNS_CHILD 0x700f
316 {PCP_PDU_PMNS_CHILD
, "PMNS_CHILD" },
317 #define PCP_PDU_PMNS_TRAVERSE 0x7010 /*also type FINISH as per pcp headers, but I can not see it used */
318 {PCP_PDU_PMNS_TRAVERSE
, "PMNS_TRAVERSE" },
319 #define PCP_PDU_USER_AUTH 0x7011
320 {PCP_PDU_USER_AUTH
, "USER_AUTH" },
321 #define PCP_PDU_LABEL_REQ 0x7012
322 {PCP_PDU_LABEL_REQ
, "LABEL_REQ" },
323 #define PCP_PDU_LABEL 0x7013
324 {PCP_PDU_LABEL
, "LABEL" },
328 static const value_string packettypenames_pm_units_space
[] = {
329 { 0, "PM_SPACE_BYTE" },
330 { 1, "PM_SPACE_KBYTE" },
331 { 2, "PM_SPACE_MBYTE" },
332 { 3, "PM_SPACE_GBYTE" },
333 { 4, "PM_SPACE_TBYTE" },
334 { 5, "PM_SPACE_PBYTE" },
335 { 6, "PM_SPACE_EBYTE" },
339 static const value_string packettypenames_pm_units_time
[] = {
340 { 0, "PM_TIME_NSEC" },
341 { 1, "PM_TIME_USEC" },
342 { 2, "PM_TIME_MSEC" },
343 { 3, "PM_TIME_SEC" },
344 { 4, "PM_TIME_MIN" },
345 { 5, "PM_TIME_HOUR" },
349 static const value_string packettypenames_pm_types
[] = {
350 #define PM_TYPE_NOSUPPORT -1
351 { -1, "PM_TYPE_NOSUPPORT" },
354 #define PM_TYPE_U32 1
355 { 1, "PM_TYPE_U32" },
358 #define PM_TYPE_U64 3
359 { 3, "PM_TYPE_U64" },
360 #define PM_TYPE_FLOAT 4
361 { 4, "PM_TYPE_FLOAT" },
362 #define PM_TYPE_DOUBLE 5
363 { 5, "PM_TYPE_DOUBLE" },
364 #define PM_TYPE_STRING 6
365 { 6, "PM_TYPE_STRING" },
366 #define PM_TYPE_AGGREGATE 7
367 { 7, "PM_TYPE_AGGREGATE" },
368 #define PM_TYPE_AGGREGATE_STATIC 8
369 { 8, "PM_TYPE_AGGREGATE_STATIC" },
370 #define PM_TYPE_EVENT 9
371 { 9, "PM_TYPE_EVENT" },
372 #define PM_TYPE_UNKNOWN 255
373 { 255, "PM_TYPE_UNKNOWN" },
377 static const value_string packettypenames_pm_types_sem
[] = {
378 { 1, "PM_SEM_COUNTER" },
379 { 3, "PM_SEM_INSTANT" },
380 { 4, "PM_SEM_DISCRETE" },
384 static const value_string packettypenames_text_type_format
[] = {
385 #define PM_TEXT_ONELINE 1
386 { 1, "PM_TEXT_ONELINE" },
387 #define PM_TEXT_HELP 2
388 { 2, "PM_TEXT_HELP" },
392 static const value_string packettypenames_text_type_ident
[] = {
393 #define PM_TEXT_PMID 4
394 { 1, "PM_TEXT_PMID" },
395 #define PM_TEXT_INDOM 8
396 { 2, "PM_TEXT_INDOM" },
400 static const value_string packettypenames_valfmt
[] = {
401 #define PM_VAL_INSITU 0
402 { 0, "PM_VAL_INSITU" },
403 #define PM_VAL_DPTR 1
404 { 1, "PM_VAL_DPTR" },
405 #define PM_VAL_SPTR 2
406 { 2, "PM_VAL_SPTR" },
410 static const value_string packettypenames_errors
[] = {
411 { -12345, "PM_ERR_GENERIC" },
412 { -12346, "PM_ERR_PMNS" },
413 { -12347, "PM_ERR_NOPMNS" },
414 { -12348, "PM_ERR_DUPPMNS" },
415 { -12349, "PM_ERR_TEXT" },
416 { -12350, "PM_ERR_APPVERSION" },
417 { -12351, "PM_ERR_VALUE" },
418 { -12352, "PM_ERR_LICENSE" },
419 { -12353, "PM_ERR_TIMEOUT" },
420 { -12354, "PM_ERR_NODATA" },
421 { -12355, "PM_ERR_RESET" },
422 { -12356, "PM_ERR_FILE" },
423 { PM_ERR_NAME
, "PM_ERR_NAME" },
424 { -12358, "PM_ERR_PMID" },
425 { -12359, "PM_ERR_INDOM" },
426 { -12360, "PM_ERR_INST" },
427 { -12361, "PM_ERR_UNIT" },
428 { -12362, "PM_ERR_CONV" },
429 { -12363, "PM_ERR_TRUNC" },
430 { -12364, "PM_ERR_SIGN" },
431 { -12365, "PM_ERR_PROFILE" },
432 { -12366, "PM_ERR_IPC" },
433 { -12367, "PM_ERR_NOASCII" },
434 { -12368, "PM_ERR_EOF" },
435 { -12369, "PM_ERR_NOTHOST" },
436 { -12370, "PM_ERR_EOL" },
437 { -12371, "PM_ERR_MODE" },
438 { -12372, "PM_ERR_LABEL" },
439 { -12373, "PM_ERR_LOGREC" },
440 { -12374, "PM_ERR_NOTARCHIVE" },
441 { -12375, "PM_ERR_LOGFILE" },
442 { -12376, "PM_ERR_NOCONTEXT" },
443 { -12377, "PM_ERR_PROFILESPEC" },
444 { -12378, "PM_ERR_PMID_LOG" },
445 { -12379, "PM_ERR_INDOM_LOG" },
446 { -12380, "PM_ERR_INST_LOG" },
447 { -12381, "PM_ERR_NOPROFILE" },
448 { -12386, "PM_ERR_NOAGENT" },
449 { -12387, "PM_ERR_PERMISSION" },
450 { -12388, "PM_ERR_CONNLIMIT" },
451 { -12389, "PM_ERR_AGAIN" },
452 { -12390, "PM_ERR_ISCONN" },
453 { -12391, "PM_ERR_NOTCONN" },
454 { -12392, "PM_ERR_NEEDPORT" },
455 { -12393, "PM_ERR_WANTACK" },
456 { -12394, "PM_ERR_NONLEAF" },
457 { -12395, "PM_ERR_OBJSTYLE" },
458 { -12396, "PM_ERR_PMCDLICENSE" },
459 { -12397, "PM_ERR_TYPE" },
460 { -12442, "PM_ERR_CTXBUSY" },
461 { -12443, "PM_ERR_TOOSMALL" },
462 { -12444, "PM_ERR_TOOBIG" },
463 { -13393, "PM_ERR_PMDAREADY" },
464 { -13394, "PM_ERR_PMDANOTREADY" },
465 { -21344, "PM_ERR_NYI" },
469 static const value_string packettypenames_creds
[]= {
475 static const value_string packettypenames_label_req_type
[]= {
476 { 1, "PM_LABEL_CONTEXT" },
477 { 2, "PM_LABEL_DOMAIN" },
478 { 4, "PM_LABEL_INDOM" },
479 { 8, "PM_LABEL_CLUSTER" },
480 { 16, "PM_LABEL_ITEM" },
481 { 32, "PM_LABEL_INSTANCES" },
485 typedef struct pcp_conv_info_t
{
486 wmem_array_t
*pmid_name_candidates
;
487 wmem_map_t
*pmid_to_name
;
488 uint32_t last_pmns_names_frame
;
489 uint32_t last_processed_pmns_names_frame
;
490 bool using_good_labels
;
493 /* function prototypes */
494 static pcp_conv_info_t
* get_pcp_conversation_info(packet_info
*pinfo
);
495 static int is_unvisited_pmns_names_frame(packet_info
*pinfo
);
496 static bool is_using_good_labels(packet_info
*pinfo
);
497 static bool label_value_length_looks_like_wrong_endianness(tvbuff_t
*tvb
, uint16_t value_offset
, uint16_t value_length
);
498 static void add_candidate_name_for_pmid_resolution(packet_info
*pinfo
, tvbuff_t
*tvb
, int offset
, int name_len
);
499 static void mark_this_frame_as_last_pmns_names_frame(packet_info
*pinfo
);
500 static inline int has_unprocessed_pmns_names_frame(pcp_conv_info_t
*pcp_conv_info
);
501 static void create_pmid_to_name_map_from_candidates(pcp_conv_info_t
*pcp_conv_info
, tvbuff_t
*tvb
, int offset
, uint32_t num_ids
);
502 static void populate_pmids_to_names(packet_info
*pinfo
, tvbuff_t
*tvb
, int offset
, uint32_t num_ids
);
503 static inline int client_to_server(packet_info
*pinfo
);
504 static inline int server_to_client(packet_info
*pinfo
);
505 static uint8_t* get_name_from_pmid(uint32_t pmid
, packet_info
*pinfo
);
506 static unsigned get_pcp_message_len(packet_info
*pinfo
, tvbuff_t
*tvb
, int offset
, void *data
);
507 static const char *get_pcp_features_to_string(wmem_allocator_t
*pool
, uint16_t feature_flags
);
508 static int dissect_pcp_message_creds(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
);
509 static int dissect_pcp_message_error(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
);
510 static int dissect_pcp_message_start(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
);
511 static int dissect_pcp_message_pmns_traverse(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
);
512 static int dissect_pcp_message_pmns_names(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
);
513 static int dissect_pcp_message_pmns_child(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
);
514 static int dissect_pcp_message_pmns_ids(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
);
515 static int dissect_pcp_message_profile(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
);
516 static int dissect_pcp_message_fetch(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
);
517 static int dissect_pcp_message_result(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
);
518 static int dissect_pcp_message_desc_req(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
);
519 static int dissect_pcp_message_desc(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
);
520 static int dissect_pcp_message_instance_req(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
);
521 static int dissect_pcp_message_instance(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
);
522 static int dissect_pcp_message_text_req(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
);
523 static int dissect_pcp_message_text(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
);
524 static int dissect_pcp_message_user_auth(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
);
525 static int dissect_pcp_partial_pmid(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
);
526 static int dissect_pcp_partial_when(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
);
527 static int dissect_pcp_partial_features(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
);
528 static int dissect_pcp_partial_label(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
, uint32_t json_start_offset
);
529 static int dissect_pcp_partial_labelset(tvbuff_t
*tvb
, proto_tree
*tree
, packet_info
*pinfo
, int offset
);
531 /* message length for dissect_tcp */
532 static unsigned get_pcp_message_len(packet_info
*pinfo _U_
, tvbuff_t
*tvb
,
533 int offset
, void *data _U_
)
535 /* length is at the very start of the packet, after tcp header */
536 return (unsigned)tvb_get_ntohl(tvb
, offset
);
539 static void mark_this_frame_as_last_pmns_names_frame(packet_info
*pinfo
) {
540 pcp_conv_info_t
*pcp_conv_info
;
541 pcp_conv_info
= get_pcp_conversation_info(pinfo
);
543 if(pinfo
->num
> pcp_conv_info
->last_pmns_names_frame
) {
544 pcp_conv_info
->last_pmns_names_frame
= pinfo
->num
;
548 static inline int has_unprocessed_pmns_names_frame(pcp_conv_info_t
*pcp_conv_info
) {
549 return pcp_conv_info
->last_pmns_names_frame
> pcp_conv_info
->last_processed_pmns_names_frame
;
552 static inline int client_to_server(packet_info
*pinfo
) {
553 return pinfo
->destport
== PCP_PORT
|| pinfo
->destport
== PMPROXY_PORT
;
556 static inline int server_to_client(packet_info
*pinfo
) {
557 return !client_to_server(pinfo
);
560 static uint8_t* get_name_from_pmid(uint32_t pmid
, packet_info
*pinfo
) {
562 wmem_map_t
*pmid_to_name
;
564 pmid_to_name
= get_pcp_conversation_info(pinfo
)->pmid_to_name
;
566 name
= (uint8_t*)wmem_map_lookup(pmid_to_name
, GINT_TO_POINTER(pmid
));
568 name
= (uint8_t*)wmem_strdup(pinfo
->pool
, "Metric name unknown");
574 static const char *get_pcp_features_to_string(wmem_allocator_t
*pool
, uint16_t feature_flags
)
576 const value_string
*flag_under_test
;
577 wmem_strbuf_t
*string_buffer
;
578 size_t string_length
;
580 string_buffer
= wmem_strbuf_new(pool
, "");
582 /* Build the comma-separated list of feature flags as a string. EG 'SECURE, COMPRESS, AUTH, ' */
583 flag_under_test
= &pcp_feature_flags
[0];
584 while (flag_under_test
->value
) {
585 if (feature_flags
& flag_under_test
->value
) {
586 wmem_strbuf_append_printf(string_buffer
, "%s, ", flag_under_test
->strptr
);
591 /* Cleanup the last remaining ', ' from the string */
592 string_length
= wmem_strbuf_get_len(string_buffer
);
593 if (string_length
> 2) {
594 wmem_strbuf_truncate(string_buffer
, string_length
- 2);
597 return wmem_strbuf_get_str(string_buffer
);
600 static pcp_conv_info_t
* get_pcp_conversation_info(packet_info
*pinfo
) {
601 conversation_t
*conversation
;
602 pcp_conv_info_t
*pcp_conv_info
;
604 conversation
= find_conversation_pinfo(pinfo
, 0);
606 /* Conversation setup is done in the main dissecting routine so it should never be null */
607 DISSECTOR_ASSERT(conversation
);
609 pcp_conv_info
= (pcp_conv_info_t
*)conversation_get_proto_data(conversation
, proto_pcp
);
611 /* Conversation data is initialized when creating the conversation so should never be null */
612 DISSECTOR_ASSERT(pcp_conv_info
);
614 return pcp_conv_info
;
617 static void add_candidate_name_for_pmid_resolution(packet_info
*pinfo
, tvbuff_t
*tvb
, int offset
, int name_len
) {
618 pcp_conv_info_t
*pcp_conv_info
;
621 pcp_conv_info
= get_pcp_conversation_info(pinfo
);
623 if(is_unvisited_pmns_names_frame(pinfo
)) {
624 name
= tvb_get_string_enc(wmem_file_scope(), tvb
, offset
, name_len
, ENC_ASCII
);
625 wmem_array_append_one(pcp_conv_info
->pmid_name_candidates
, name
);
629 static int is_unvisited_pmns_names_frame(packet_info
*pinfo
) {
630 pcp_conv_info_t
*pcp_conv_info
;
632 pcp_conv_info
= get_pcp_conversation_info(pinfo
);
634 return pinfo
->num
> pcp_conv_info
->last_processed_pmns_names_frame
&& pinfo
->num
> pcp_conv_info
->last_pmns_names_frame
;
637 static void populate_pmids_to_names(packet_info
*pinfo
, tvbuff_t
*tvb
, int offset
, uint32_t num_ids
) {
638 pcp_conv_info_t
*pcp_conv_info
;
639 unsigned number_of_name_candidates
;
641 pcp_conv_info
= get_pcp_conversation_info(pinfo
);
642 number_of_name_candidates
= wmem_array_get_count(pcp_conv_info
->pmid_name_candidates
);
644 if(number_of_name_candidates
== num_ids
&& has_unprocessed_pmns_names_frame(pcp_conv_info
)) {
645 create_pmid_to_name_map_from_candidates(pcp_conv_info
, tvb
, offset
, num_ids
);
646 /* Set this frame to the one that we processed */
647 pcp_conv_info
->last_processed_pmns_names_frame
= pcp_conv_info
->last_pmns_names_frame
;
650 pcp_conv_info
->pmid_name_candidates
= wmem_array_new(wmem_file_scope(), sizeof(uint8_t *));
653 static void create_pmid_to_name_map_from_candidates(pcp_conv_info_t
*pcp_conv_info
, tvbuff_t
*tvb
, int offset
, uint32_t num_ids
) {
656 for(i
=0; i
<num_ids
; i
++) {
660 pmid
= tvb_get_ntohl(tvb
, offset
);
661 pmid_name
= *(uint8_t **)wmem_array_index(pcp_conv_info
->pmid_name_candidates
, i
);
663 if(wmem_map_lookup(pcp_conv_info
->pmid_to_name
, GINT_TO_POINTER(pmid
)) == NULL
) {
664 wmem_map_insert(pcp_conv_info
->pmid_to_name
, GINT_TO_POINTER(pmid
), pmid_name
);
670 static int dissect_pcp_message_creds(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
)
672 uint32_t creds_length
;
675 /* append the type of packet */
676 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "[%s]",
677 val_to_str(PCP_PDU_CREDS
, packettypenames
, "Unknown Type:0x%02x"));
679 /* first is the number of creds */
680 proto_tree_add_item(tree
, hf_pcp_creds_number_of
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
681 /* store the number of creds so we know how long to interate for */
682 creds_length
= tvb_get_ntohl(tvb
, offset
);
684 /* go through each __pmVersionCred struct */
685 for (i
= 0; i
< creds_length
; i
++) {
686 /* __pmVersionCred.c_type */
687 proto_tree_add_item(tree
, hf_pcp_creds_type
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
689 /* __pmVersionCred.c_version */
690 proto_tree_add_item(tree
, hf_pcp_creds_version
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
692 /* __pmVersionCred.c_flags */
693 offset
= dissect_pcp_partial_features(tvb
, pinfo
, tree
, offset
);
698 /* ERROR packet format:
701 static int dissect_pcp_message_error(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
)
704 pcp_conv_info_t
*pcp_conv_info
;
706 /* append the type of packet, we can't look this up as it clashes with START */
707 col_append_str(pinfo
->cinfo
, COL_INFO
, "[ERROR] ");
709 /* add the error item to the tree and column */
710 proto_tree_add_item(tree
, hf_pcp_pdu_error
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
711 error_num
= tvb_get_ntohl(tvb
, offset
);
712 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "error=%s ",
713 val_to_str(error_num
, packettypenames_errors
, "Unknown Error:%i"));
716 /* Clean out candidate names if we got an error from a PMNS_NAMES lookup. This will allow subsequent PMNS_NAMES
717 lookups to work in the same conversation
719 if(error_num
== PM_ERR_NAME
) {
720 pcp_conv_info
= get_pcp_conversation_info(pinfo
);
721 pcp_conv_info
->pmid_name_candidates
= wmem_array_new(wmem_file_scope(), sizeof(uint8_t *));
727 /* START packet format:
731 |> unsigned int zero : 1 bit
732 unsigned int version : 7 bits
733 unsigned int licensed : 8 bits
734 unsigned int features : 16 bits
736 static int dissect_pcp_message_start(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
)
738 /* create a start tree to hold the information*/
739 proto_item
*pcp_start_item
;
740 proto_tree
*pcp_start_tree
;
743 pcp_start_item
= proto_tree_add_item(tree
, hf_pcp_start
, tvb
, 0, -1, ENC_NA
);
744 pcp_start_tree
= proto_item_add_subtree(pcp_start_item
, ett_pcp
);
746 /* append the type of packet, we can't look this up as it clashes with ERROR */
747 col_append_str(pinfo
->cinfo
, COL_INFO
, "[START]");
750 status
= tvb_get_ntohl(tvb
, offset
);
751 proto_tree_add_item(pcp_start_tree
, hf_pcp_start_status
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
753 if(tvb_reported_length_remaining(tvb
, offset
) == 0){
754 /* Most likely we're in a SSL upgrade if this is the end of the start packet */
755 if(status
== PCP_SECURE_ACK_SUCCESSFUL
) {
756 expert_add_info(pinfo
, tree
, &ei_pcp_ssl_upgrade
);
757 ssl_starttls_ack(find_dissector("tls"), pinfo
, pcp_handle
);
760 expert_add_info(pinfo
, tree
, &ei_pcp_ssl_upgrade_failed
);
764 /* zero bit and version bits */
765 proto_tree_add_item(pcp_start_tree
, hf_pcp_start_zero
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
766 proto_tree_add_item(pcp_start_tree
, hf_pcp_start_version
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
769 proto_tree_add_item(pcp_start_tree
, hf_pcp_start_licensed
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
772 offset
= dissect_pcp_partial_features(tvb
, pinfo
, pcp_start_tree
, offset
);
777 /* PMNS_TRAVERSE packet format:
780 char name[sizeof(namelen)] + padding
782 static int dissect_pcp_message_pmns_traverse(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
)
784 proto_item
*pcp_pmns_traverse_item
;
785 proto_tree
*pcp_pmns_traverse_tree
;
789 /* append the type of packet */
790 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "[%s]",
791 val_to_str(PCP_PDU_PMNS_TRAVERSE
, packettypenames
, "Unknown Type:0x%02x"));
793 pcp_pmns_traverse_item
= proto_tree_add_item(tree
, hf_pcp_pmns_traverse
, tvb
, offset
, -1, ENC_NA
);
794 pcp_pmns_traverse_tree
= proto_item_add_subtree(pcp_pmns_traverse_item
, ett_pcp
);
797 proto_tree_add_item(pcp_pmns_traverse_tree
, hf_pcp_pmns_subtype
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
800 proto_tree_add_item(pcp_pmns_traverse_tree
, hf_pcp_pmns_namelen
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
801 name_len
= tvb_get_ntohl(tvb
, offset
); /* get the actual length out so we can use it in the next item */
804 proto_tree_add_item(pcp_pmns_traverse_tree
, hf_pcp_pmns_name
, tvb
, offset
, name_len
, ENC_ASCII
);
805 offset
+= name_len
; /* increment by whatever the length of the name string was */
807 /* "padding" (not really padding, just what is left over in the old buffer) */
808 padding
= name_len
% 4; /* names are padded to the nearest 4 byte boundary */
809 if (padding
!= 0) { /* if there is padding, keep going till the remainder of mod 4 */
810 padding
= 4 - padding
; /* we want the inverse of the remainder */
812 proto_tree_add_item(pcp_pmns_traverse_tree
, hf_pcp_pdu_padding
, tvb
, offset
, padding
, ENC_NA
);
818 /* PMNS_NAMES packet format:
819 uint32_t nstrbytes (number of str bytes)
820 uint32_t numstatus (0 if no status. Also, if 0, use name_t, otherwise use name_status_t )
822 __pmPDU names (if numstatus = 0, filled with name_t, otherwise name_status_t)
826 | char name[sizeof(namelen)]
828 |> -- name_status_t --
831 char name[sizeof(namelen)]
833 static int dissect_pcp_message_pmns_names(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
)
835 proto_item
*pcp_pmns_names_item
;
836 proto_tree
*pcp_pmns_names_tree
;
837 proto_item
*pcp_pmns_names_name_item
;
838 proto_tree
*pcp_pmns_names_name_tree
;
839 uint32_t is_pmns_names_status
;
842 uint32_t full_name_len
;
846 /* append the type of packet */
847 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "[%s]", val_to_str(PCP_PDU_PMNS_NAMES
, packettypenames
, "Unknown Type:0x%02x"));
849 pcp_pmns_names_item
= proto_tree_add_item(tree
, hf_pcp_pmns_names
, tvb
, offset
, -1, ENC_NA
);
850 pcp_pmns_names_tree
= proto_item_add_subtree(pcp_pmns_names_item
, ett_pcp
);
853 proto_tree_add_item(pcp_pmns_names_tree
, hf_pcp_pmns_names_nstrbytes
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
857 proto_tree_add_item(pcp_pmns_names_tree
, hf_pcp_pmns_names_numstatus
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
858 is_pmns_names_status
= tvb_get_ntohl(tvb
, offset
); /* is the status also present in this PDU? */
862 proto_tree_add_item(pcp_pmns_names_tree
, hf_pcp_pmns_names_numnames
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
863 num_names
= tvb_get_ntohl(tvb
, offset
); /* get the number of names to iterate through */
867 for (i
=0; i
< num_names
; i
++) {
868 /* find out the size of the name_t/name_status_t before we create the tree */
869 if (is_pmns_names_status
) {
870 name_len
= tvb_get_ntohl(tvb
, offset
+4);
871 full_name_len
= name_len
+ 8;
873 name_len
= tvb_get_ntohl(tvb
, offset
);
874 full_name_len
= name_len
+ 4;
876 /* add a new subtree for each name */
877 pcp_pmns_names_name_item
= proto_tree_add_item(pcp_pmns_names_tree
, hf_pcp_pmns_names_nametree
,
878 tvb
, offset
, full_name_len
, ENC_NA
);
879 pcp_pmns_names_name_tree
= proto_item_add_subtree(pcp_pmns_names_name_item
, ett_pcp
);
881 if (is_pmns_names_status
) {
882 /* print out the name status and increment if we're supposed to have it */
883 proto_tree_add_item(pcp_pmns_names_name_tree
, hf_pcp_pmns_names_nametree_status
,
884 tvb
, offset
, 4, ENC_BIG_ENDIAN
);
888 proto_tree_add_item(pcp_pmns_names_name_tree
, hf_pcp_pmns_names_nametree_namelen
,
889 tvb
, offset
, 4, ENC_BIG_ENDIAN
);
892 if(client_to_server(pinfo
)) {
893 add_candidate_name_for_pmid_resolution(pinfo
, tvb
, offset
, name_len
);
895 proto_tree_add_item(pcp_pmns_names_name_tree
, hf_pcp_pmns_names_nametree_name
,
896 tvb
, offset
, name_len
, ENC_ASCII
);
899 padding
= name_len
% 4; /* names are padded to the nearest 4 byte boundary */
901 padding
= 4 - padding
; /* we want the inverse of the remainder */
902 /* if there is padding, keep going till the remainder of mod 8 */
903 proto_tree_add_item(pcp_pmns_names_name_tree
, hf_pcp_pdu_padding
, tvb
, offset
, padding
, ENC_NA
);
907 if(client_to_server(pinfo
)) {
908 mark_this_frame_as_last_pmns_names_frame(pinfo
);
913 /* PMNS_CHILD packet format:
918 static int dissect_pcp_message_pmns_child(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
)
920 proto_item
*pcp_pmns_child_item
;
921 proto_tree
*pcp_pmns_child_tree
;
924 pcp_pmns_child_item
= proto_tree_add_item(tree
, hf_pcp_pmns_child
, tvb
, offset
, -1, ENC_NA
);
925 pcp_pmns_child_tree
= proto_item_add_subtree(pcp_pmns_child_item
, ett_pcp
);
927 /* append the type of packet */
928 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "[%s]", val_to_str(PCP_PDU_PMNS_CHILD
, packettypenames
, "Unknown Type:0x%02x"));
931 proto_tree_add_item(pcp_pmns_child_tree
, hf_pcp_pmns_subtype
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
935 proto_tree_add_item(pcp_pmns_child_tree
, hf_pcp_pmns_namelen
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
936 name_len
= tvb_get_ntohl(tvb
, offset
); /* length of the next value */
940 proto_tree_add_item(pcp_pmns_child_tree
, hf_pcp_pmns_name
, tvb
, offset
, name_len
, ENC_ASCII
);
945 /* PMNS_IDS packet format
948 pmID idlist[numids] (where pmID = uint32)
951 static int dissect_pcp_message_pmns_ids(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
)
953 proto_item
*pcp_pmns_ids_item
;
954 proto_tree
*pcp_pmns_ids_tree
;
958 /* append the type of packet */
959 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "[%s]",
960 val_to_str(PCP_PDU_PMNS_IDS
, packettypenames
, "Unknown Type:0x%02x"));
962 pcp_pmns_ids_item
= proto_tree_add_item(tree
, hf_pcp_pmns_ids
, tvb
, offset
, -1, ENC_NA
);
963 pcp_pmns_ids_tree
= proto_item_add_subtree(pcp_pmns_ids_item
, ett_pcp
);
966 proto_tree_add_item(pcp_pmns_ids_tree
, hf_pcp_pmns_ids_status
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
970 proto_tree_add_item(pcp_pmns_ids_tree
, hf_pcp_pmns_ids_numids
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
971 num_ids
= tvb_get_ntohl(tvb
, offset
);
974 /* Populate the PMID to name mapping */
975 populate_pmids_to_names(pinfo
, tvb
, offset
, num_ids
);
978 for (i
=0; i
<num_ids
; i
++) {
980 offset
= dissect_pcp_partial_pmid(tvb
, pinfo
, pcp_pmns_ids_tree
, offset
);
985 /* PROFILE packet format
990 pmProfile profiles[numprof]
997 static int dissect_pcp_message_profile(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
)
999 proto_item
*pcp_profile_item
;
1000 proto_tree
*pcp_profile_tree
;
1001 proto_item
*pcp_profile_profile_item
;
1002 proto_tree
*pcp_profile_profile_tree
;
1006 /* append the type of packet */
1007 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "[%s]", val_to_str(PCP_PDU_PROFILE
, packettypenames
, "Unknown Type:0x%02x"));
1009 pcp_profile_item
= proto_tree_add_item(tree
, hf_pcp_profile
, tvb
, offset
, -1, ENC_NA
);
1010 pcp_profile_tree
= proto_item_add_subtree(pcp_profile_item
, ett_pcp
);
1013 proto_tree_add_item(pcp_profile_tree
, hf_pcp_ctxnum
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1017 proto_tree_add_item(pcp_profile_tree
, hf_pcp_profile_g_state
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1021 proto_tree_add_item(pcp_profile_tree
, hf_pcp_profile_numprof
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1022 num_prof
= tvb_get_ntohl(tvb
, offset
);
1026 proto_tree_add_item(pcp_profile_tree
, hf_pcp_pdu_padding
, tvb
, offset
, 4, ENC_NA
);
1029 /* iterate through each profile */
1030 for (i
=0; i
<num_prof
; i
++) {
1031 /* subtree for each profile */
1032 pcp_profile_profile_item
= proto_tree_add_item(pcp_profile_tree
, hf_pcp_profile_profile
, tvb
, offset
, 32, ENC_NA
);
1033 pcp_profile_profile_tree
= proto_item_add_subtree(pcp_profile_profile_item
, ett_pcp
);
1036 proto_tree_add_item(pcp_profile_profile_tree
, hf_pcp_instance_indom
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1039 /* state - include/exclude */
1040 proto_tree_add_item(pcp_profile_profile_tree
, hf_pcp_profile_profile_state
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1043 /* numinst - number of instances to follow */
1044 proto_tree_add_item(pcp_profile_profile_tree
, hf_pcp_profile_profile_numinst
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1048 proto_tree_add_item(pcp_profile_tree
, hf_pcp_pdu_padding
, tvb
, offset
, 4, ENC_NA
);
1054 /* FETCH packet format
1056 __pmTimeval when (unsigned int tv_sec, unsigned int tv_usec)
1058 pmID pmidlist[1-x] (unsigned int)
1060 static int dissect_pcp_message_fetch(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
)
1062 proto_item
*pcp_fetch_item
;
1063 proto_tree
*pcp_fetch_tree
;
1067 /* append the type of packet */
1068 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "[%s]",
1069 val_to_str(PCP_PDU_FETCH
, packettypenames
, "Unknown Type:0x%02x"));
1071 pcp_fetch_item
= proto_tree_add_item(tree
, hf_pcp_fetch
, tvb
, offset
, -1, ENC_NA
);
1072 pcp_fetch_tree
= proto_item_add_subtree(pcp_fetch_item
, ett_pcp
);
1075 proto_tree_add_item(pcp_fetch_tree
, hf_pcp_ctxnum
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1079 offset
= dissect_pcp_partial_when(tvb
, pinfo
, pcp_fetch_tree
, offset
);
1082 proto_tree_add_item(pcp_fetch_tree
, hf_pcp_fetch_numpmid
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1083 num_pmid
= tvb_get_ntohl(tvb
, offset
);
1087 for (i
=0; i
<num_pmid
; i
++) {
1088 /* decode partial PMID message */
1089 offset
= dissect_pcp_partial_pmid(tvb
, pinfo
, pcp_fetch_tree
, offset
);
1094 /* RESULT packet format
1096 __pmTimeval when (unsigned int tv_sec, unsigned int tv_usec)
1098 _pmPDU data[1-n] (contains v_list types)
1103 __pmValue_PDU vlist[1-n] (contains pmValue PDUs)
1107 (if valfmt == PTR type)
1112 static int dissect_pcp_message_result(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
)
1114 proto_item
*pcp_results_item
;
1115 proto_tree
*pcp_results_tree
;
1116 proto_item
*pcp_result_item
;
1117 proto_tree
*pcp_result_tree
;
1118 proto_item
*pcp_result_instance_item
;
1119 proto_tree
*pcp_result_instance_tree
;
1122 uint32_t offset_start
;
1123 uint32_t valfmt_type
;
1124 uint32_t value_type
;
1125 uint32_t pmvalueblock_offset
;
1126 uint32_t pmvalueblock_value_length
;
1130 /* append the type of packet */
1131 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "[%s]", val_to_str(PCP_PDU_RESULT
, packettypenames
, "Unknown Type:0x%02x"));
1133 pcp_results_item
= proto_tree_add_item(tree
, hf_pcp_results
, tvb
, offset
, -1, ENC_NA
);
1134 pcp_results_tree
= proto_item_add_subtree(pcp_results_item
, ett_pcp
);
1137 offset
= dissect_pcp_partial_when(tvb
, pinfo
, pcp_results_tree
, offset
);
1140 proto_tree_add_item(pcp_results_tree
, hf_pcp_results_numpmid
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1141 num_pmid
= tvb_get_ntohl(tvb
, offset
);
1145 for (i
=0; i
<num_pmid
; i
++) {
1146 /* work out how long each result should be - set starting offset */
1147 offset_start
= offset
;
1149 pcp_result_item
= proto_tree_add_item(pcp_results_tree
, hf_pcp_result
, tvb
, offset
, -1, ENC_NA
);
1150 pcp_result_tree
= proto_item_add_subtree(pcp_result_item
, ett_pcp
);
1153 offset
= dissect_pcp_partial_pmid(tvb
, pinfo
, pcp_result_tree
, offset
);
1156 proto_tree_add_item(pcp_result_tree
, hf_pcp_result_numval
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1157 num_val
= tvb_get_ntohl(tvb
, offset
);
1160 /* if there are no numvals, then the valfmt isn't sent */
1164 proto_tree_add_item(pcp_result_tree
, hf_pcp_result_valfmt
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1165 valfmt_type
= tvb_get_ntohl(tvb
, offset
);
1169 for (j
=0; j
<num_val
; j
++) {
1170 /* give the subtree name length of inst (int) + offset/va (int) */
1171 pcp_result_instance_item
= proto_tree_add_item(pcp_result_tree
, hf_pcp_instance
,
1172 tvb
, offset
, 8, ENC_NA
);
1173 pcp_result_instance_tree
= proto_item_add_subtree(pcp_result_instance_item
, ett_pcp
);
1176 proto_tree_add_item(pcp_result_instance_tree
, hf_pcp_pmid_inst
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1179 /* valoffset/value: depending on the format, the next 32 bits is the value _OR_ the offset to where
1181 if (valfmt_type
== PM_VAL_INSITU
) {
1182 proto_tree_add_item(pcp_result_instance_tree
, hf_pcp_instance_value_insitu
,
1183 tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1185 /* offset in the packet to find pmValueBlock */
1186 proto_tree_add_item(pcp_result_instance_tree
, hf_pcp_instance_valoffset
,
1187 tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1188 /* get the offset (not the offset of the count we are at) but where we should look */
1189 pmvalueblock_offset
= tvb_get_ntohl(tvb
, offset
);
1190 pmvalueblock_offset
= pmvalueblock_offset
* 4; /* offset values are in 32bit units */
1193 value_type
= tvb_get_uint8(tvb
, pmvalueblock_offset
);
1194 proto_tree_add_item(pcp_result_instance_tree
, hf_pcp_pmid_type
,
1195 tvb
, pmvalueblock_offset
, 1, ENC_BIG_ENDIAN
);
1196 pmvalueblock_offset
+= 1;
1199 pmvalueblock_value_length
= tvb_get_ntoh24(tvb
, pmvalueblock_offset
);
1200 /* can't add a tree item the ususal way as it is outside of the tree */
1201 proto_tree_add_item(pcp_result_instance_tree
, hf_pcp_instance_vallength
,
1202 tvb
, pmvalueblock_offset
, 3, ENC_BIG_ENDIAN
);
1203 pmvalueblock_offset
+= 3;
1205 /* value - note we go up to the pmvalueblock_value_length - 4,
1206 as this value includes the previous 4 bytes */
1207 switch (value_type
) {
1209 proto_tree_add_item(pcp_result_instance_tree
, hf_pcp_instance_value_int
, tvb
,
1210 pmvalueblock_offset
, pmvalueblock_value_length
-4, ENC_BIG_ENDIAN
);
1213 proto_tree_add_item(pcp_result_instance_tree
, hf_pcp_instance_value_uint
, tvb
,
1214 pmvalueblock_offset
, pmvalueblock_value_length
-4, ENC_BIG_ENDIAN
);
1217 proto_tree_add_item(pcp_result_instance_tree
, hf_pcp_instance_value_int64
, tvb
,
1218 pmvalueblock_offset
, pmvalueblock_value_length
-4, ENC_BIG_ENDIAN
);
1221 proto_tree_add_item(pcp_result_instance_tree
, hf_pcp_instance_value_uint64
, tvb
,
1222 pmvalueblock_offset
, pmvalueblock_value_length
-4, ENC_BIG_ENDIAN
);
1225 proto_tree_add_item(pcp_result_instance_tree
, hf_pcp_instance_value_float
, tvb
,
1226 pmvalueblock_offset
, pmvalueblock_value_length
-4, ENC_BIG_ENDIAN
);
1228 case PM_TYPE_DOUBLE
:
1229 proto_tree_add_item(pcp_result_instance_tree
, hf_pcp_instance_value_double
, tvb
,
1230 pmvalueblock_offset
, pmvalueblock_value_length
-4, ENC_BIG_ENDIAN
);
1232 case PM_TYPE_STRING
:
1233 proto_tree_add_item(pcp_result_instance_tree
, hf_pcp_instance_value_ptr
, tvb
,
1234 pmvalueblock_offset
, pmvalueblock_value_length
-4, ENC_ASCII
);
1236 case PM_TYPE_AGGREGATE
:
1237 case PM_TYPE_AGGREGATE_STATIC
:
1238 proto_tree_add_item(pcp_result_instance_tree
, hf_pcp_instance_value_aggr
, tvb
,
1239 pmvalueblock_offset
, pmvalueblock_value_length
-4, ENC_NA
);
1242 expert_add_info(pinfo
, pcp_result_instance_tree
, &ei_pcp_type_event_unimplemented
);
1244 case PM_TYPE_NOSUPPORT
:
1245 expert_add_info(pinfo
, pcp_result_instance_tree
, &ei_pcp_type_nosupport_unsupported
);
1247 case PM_TYPE_UNKNOWN
:
1248 expert_add_info(pinfo
, pcp_result_instance_tree
, &ei_pcp_type_unknown_unknown_value
);
1251 expert_add_info(pinfo
, pcp_result_instance_tree
, &ei_pcp_unimplemented_value
);
1255 /* bump the offset after the instance value _or_ the offset into
1256 the packet (pcp.instance.valoffset) , each being 4 bytes */
1261 /* we now know how long the field is */
1262 proto_item_set_len(pcp_result_tree
, offset
-offset_start
);
1268 /* DESC_REQ pcaket format
1269 pmID pmid (32bit int)
1271 static int dissect_pcp_message_desc_req(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
)
1273 proto_item
*pcp_desc_req_item
;
1274 proto_tree
*pcp_desc_req_tree
;
1276 /* append the type of packet */
1277 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "[%s]", val_to_str(PCP_PDU_DESC_REQ
, packettypenames
, "Unknown Type:0x%02x"));
1279 /* subtree for packet type */
1280 pcp_desc_req_item
= proto_tree_add_item(tree
, hf_pcp_desc_req
, tvb
, offset
, -1, ENC_NA
);
1281 pcp_desc_req_tree
= proto_item_add_subtree(pcp_desc_req_item
, ett_pcp
);
1283 offset
= dissect_pcp_partial_pmid(tvb
, pinfo
, pcp_desc_req_tree
, offset
);
1288 /* DESC packet format
1290 int type (base data type)
1292 int sem (semantics of the value: instant? counter? etc..)
1296 signed int dimSpace : 4
1297 signed int dimTime : 4
1298 signed int dimCount : 4
1299 unsigned int scaleSpace : 4
1300 unsigned int scaleTime : 4
1301 signed int scaleCount : 4
1302 unsigned int pad : 8
1304 static int dissect_pcp_message_desc(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
)
1306 proto_item
*pcp_desc_item
;
1307 proto_tree
*pcp_desc_tree
;
1308 proto_item
*pcp_desc_units_item
;
1309 proto_tree
*pcp_desc_units_tree
;
1310 uint32_t bits_offset
;
1312 /* append the type of packet */
1313 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "[%s]", val_to_str(PCP_PDU_DESC
, packettypenames
, "Unknown Type:0x%02x"));
1315 /* root desc tree */
1316 pcp_desc_item
= proto_tree_add_item(tree
, hf_pcp_desc
, tvb
, offset
, 4, ENC_NA
);
1317 pcp_desc_tree
= proto_item_add_subtree(pcp_desc_item
, ett_pcp
);
1320 offset
= dissect_pcp_partial_pmid(tvb
, pinfo
, pcp_desc_tree
, offset
);
1323 proto_tree_add_item(pcp_desc_tree
, hf_pcp_pmid_type
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1327 proto_tree_add_item(pcp_desc_tree
, hf_pcp_instance_indom
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1331 proto_tree_add_item(pcp_desc_tree
, hf_pcp_pmid_sem
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1335 bits_offset
= offset
*8; /* create the bits offset */
1336 pcp_desc_units_item
= proto_tree_add_item(pcp_desc_tree
, hf_pcp_units
, tvb
, offset
, -1, ENC_NA
);
1337 pcp_desc_units_tree
= proto_item_add_subtree(pcp_desc_units_item
, ett_pcp
);
1340 proto_tree_add_bits_item(pcp_desc_units_tree
, hf_pcp_units_dimspace
, tvb
, bits_offset
, 4, ENC_BIG_ENDIAN
);
1343 proto_tree_add_bits_item(pcp_desc_units_tree
, hf_pcp_units_dimtime
, tvb
, bits_offset
, 4, ENC_BIG_ENDIAN
);
1346 proto_tree_add_bits_item(pcp_desc_units_tree
, hf_pcp_units_dimcount
, tvb
, bits_offset
, 4, ENC_BIG_ENDIAN
);
1349 proto_tree_add_bits_item(pcp_desc_units_tree
, hf_pcp_units_scalespace
, tvb
, bits_offset
, 4, ENC_BIG_ENDIAN
);
1352 proto_tree_add_bits_item(pcp_desc_units_tree
, hf_pcp_units_scaletime
, tvb
, bits_offset
, 4, ENC_BIG_ENDIAN
);
1355 proto_tree_add_bits_item(pcp_desc_units_tree
, hf_pcp_units_scalecount
, tvb
, bits_offset
, 4, ENC_BIG_ENDIAN
);
1356 /*bits_offset += 4;*/
1358 offset
+= 3; /* total offset of pmunits before */
1359 proto_tree_add_item(pcp_desc_units_tree
, hf_pcp_pdu_padding
, tvb
, offset
, 1, ENC_NA
);
1361 /*bits_offset += 8;*/
1366 /* INSTANCE_REQ packet format
1373 static int dissect_pcp_message_instance_req(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
)
1375 proto_item
*pcp_instance_req_item
;
1376 proto_tree
*pcp_instance_req_tree
;
1379 /* append the type of packet */
1380 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "[%s]", val_to_str(PCP_PDU_INSTANCE_REQ
, packettypenames
, "Unknown Type:0x%02x"));
1382 pcp_instance_req_item
= proto_tree_add_item(tree
, hf_pcp_instance_req
, tvb
, offset
, -1, ENC_NA
);
1383 pcp_instance_req_tree
= proto_item_add_subtree(pcp_instance_req_item
, ett_pcp
);
1386 proto_tree_add_item(pcp_instance_req_tree
, hf_pcp_instance_indom
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1390 offset
= dissect_pcp_partial_when(tvb
, pinfo
, pcp_instance_req_tree
, offset
);
1393 proto_tree_add_item(pcp_instance_req_tree
, hf_pcp_pmid_inst
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1397 proto_tree_add_item(pcp_instance_req_tree
, hf_pcp_instance_namelen
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1398 name_len
= tvb_get_ntohl(tvb
, offset
);
1403 proto_tree_add_item(pcp_instance_req_tree
, hf_pcp_instance_name
, tvb
, offset
, name_len
, ENC_ASCII
);
1409 /* TEXT_REQ packet format
1413 static int dissect_pcp_message_text_req(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
)
1415 proto_item
*pcp_text_req_item
;
1416 proto_tree
*pcp_text_req_tree
;
1417 proto_item
*pcp_text_req_type_item
;
1418 proto_tree
*pcp_text_req_type_tree
;
1419 uint32_t bits_offset
;
1422 /* append the type of packet */
1423 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "[%s]", val_to_str(PCP_PDU_TEXT_REQ
, packettypenames
, "Unknown Type:0x%02x"));
1425 pcp_text_req_item
= proto_tree_add_item(tree
, hf_pcp_text_req
, tvb
, offset
, -1, ENC_NA
);
1426 pcp_text_req_tree
= proto_item_add_subtree(pcp_text_req_item
, ett_pcp
);
1428 /* peek at type to decode ident correctly */
1429 type
= tvb_get_ntohl(tvb
, offset
+ 4);
1432 if (type
& PM_TEXT_PMID
) {
1433 offset
= dissect_pcp_partial_pmid(tvb
, pinfo
, pcp_text_req_tree
, offset
);
1434 } else if (type
& PM_TEXT_INDOM
) {
1435 proto_tree_add_item(pcp_text_req_tree
, hf_pcp_instance_indom
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1440 pcp_text_req_type_item
= proto_tree_add_item(pcp_text_req_tree
, hf_pcp_text_type
, tvb
, offset
, 4, ENC_NA
);
1441 pcp_text_req_type_tree
= proto_item_add_subtree(pcp_text_req_type_item
, ett_pcp
);
1442 bits_offset
= offset
* 8 + 28;
1443 proto_tree_add_bits_item(pcp_text_req_type_tree
, hf_pcp_text_type_ident
, tvb
, bits_offset
, 2, ENC_BIG_ENDIAN
);
1445 proto_tree_add_bits_item(pcp_text_req_type_tree
, hf_pcp_text_type_format
, tvb
, bits_offset
, 2, ENC_BIG_ENDIAN
);
1451 /* TEXT packet format
1456 static int dissect_pcp_message_text(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
)
1458 proto_item
*pcp_text_item
;
1459 proto_tree
*pcp_text_tree
;
1462 /* append the type of packet */
1463 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "[%s]", val_to_str(PCP_PDU_TEXT
, packettypenames
, "Unknown Type:0x%02x"));
1465 pcp_text_item
= proto_tree_add_item(tree
, hf_pcp_text
, tvb
, offset
, -1, ENC_NA
);
1466 pcp_text_tree
= proto_item_add_subtree(pcp_text_item
, ett_pcp
);
1469 proto_tree_add_item(pcp_text_tree
, hf_pcp_text_ident
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1473 buflen
= tvb_get_ntohl(tvb
, offset
);
1474 proto_tree_add_item(pcp_text_tree
, hf_pcp_text_buflen
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1478 proto_tree_add_item(pcp_text_tree
, hf_pcp_text_buffer
, tvb
, offset
, buflen
, ENC_ASCII
);
1484 /* USER_AUTH packet format
1489 static int dissect_pcp_message_user_auth(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
)
1491 /* append the type of packet */
1492 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "[%s]", val_to_str(PCP_PDU_USER_AUTH
, packettypenames
, "Unknown Type:0x%02x"));
1494 proto_tree_add_item(tree
, hf_pcp_user_auth_payload
, tvb
, offset
, -1, ENC_NA
);
1496 return tvb_reported_length(tvb
);
1499 /* LABEL_REQ packet format
1503 static int dissect_pcp_message_label_req(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
)
1505 /* append the type of packet */
1506 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "[%s]", val_to_str(PCP_PDU_LABEL_REQ
, packettypenames
, "Unknown Type:0x%02x"));
1508 proto_item
*pcp_label_req_item
= proto_tree_add_item(tree
, hf_pcp_label_req
, tvb
, offset
, -1, ENC_NA
);
1509 proto_tree
*pcp_label_req_tree
= proto_item_add_subtree(pcp_label_req_item
, ett_pcp
);
1512 proto_tree_add_item(pcp_label_req_tree
, hf_pcp_label_ident
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1516 proto_tree_add_item(pcp_label_req_tree
, hf_pcp_label_type
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1522 /* LABEL packet format
1535 static int dissect_pcp_message_label(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
)
1537 /* append the type of packet */
1538 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "[%s]", val_to_str(PCP_PDU_LABEL
, packettypenames
, "Unknown Type:0x%02x"));
1540 proto_item
*pcp_label_item
= proto_tree_add_item(tree
, hf_pcp_label
, tvb
, offset
, -1, ENC_NA
);
1541 proto_tree
*pcp_label_tree
= proto_item_add_subtree(pcp_label_item
, ett_pcp
);
1544 proto_tree_add_item(pcp_label_tree
, hf_pcp_label_ident
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1548 proto_tree_add_item(pcp_label_tree
, hf_pcp_label_type
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1552 proto_tree_add_item(pcp_label_tree
, hf_pcp_label_padding
, tvb
, offset
, 4, ENC_NA
);
1555 /* number of label sets */
1557 proto_tree_add_item_ret_int(pcp_label_tree
, hf_pcp_label_nsets
, tvb
, offset
, 4, ENC_NA
, &nsets
);
1561 for (int32_t i
= 0; i
< nsets
; i
++) {
1562 offset
= dissect_pcp_partial_labelset(tvb
, pcp_label_tree
, pinfo
, offset
);
1568 /* INSTANCE packet type
1571 instlist_t instlist[numinst]
1577 static int dissect_pcp_message_instance(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
)
1579 proto_item
*pcp_instances_item
;
1580 proto_tree
*pcp_instances_tree
;
1581 proto_item
*pcp_instance_item
;
1582 proto_tree
*pcp_instance_tree
;
1588 /* append the type of packet */
1589 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "[%s]", val_to_str(PCP_PDU_INSTANCE
, packettypenames
, "Unknown Type:0x%02x"));
1591 pcp_instances_item
= proto_tree_add_item(tree
, hf_pcp_instances
, tvb
, offset
, -1, ENC_NA
);
1592 pcp_instances_tree
= proto_item_add_subtree(pcp_instances_item
, ett_pcp
);
1595 proto_tree_add_item(pcp_instances_tree
, hf_pcp_instance_indom
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1598 proto_tree_add_item(pcp_instances_tree
, hf_pcp_instances_numinst
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1599 num_inst
= tvb_get_ntohl(tvb
, offset
);
1603 for (i
=0; i
<num_inst
; i
++) {
1604 /* get the size of the name first, so we know how much offset to give */
1605 name_len
= tvb_get_ntohl(tvb
, offset
+4);
1607 /* give the subtree name length + 2 ints */
1608 pcp_instance_item
= proto_tree_add_item(pcp_instances_tree
, hf_pcp_instance
, tvb
, offset
, name_len
+8, ENC_NA
);
1609 pcp_instance_tree
= proto_item_add_subtree(pcp_instance_item
, ett_pcp
);
1612 proto_tree_add_item(pcp_instance_tree
, hf_pcp_pmid_inst
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1616 proto_tree_add_item(pcp_instance_tree
, hf_pcp_instance_namelen
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1621 proto_tree_add_item(pcp_instance_tree
, hf_pcp_instance_name
, tvb
, offset
, name_len
, ENC_ASCII
);
1626 padding
= name_len
% 4; /* names are padded to the nearest 4 byte boundary */
1627 if (padding
!= 0) { /* if there is padding, keep going till the remainder of mod 4 */
1628 padding
= 4 - padding
; /* we want the inverse of the remainder */
1630 proto_tree_add_item(pcp_instance_tree
, hf_pcp_pdu_padding
, tvb
, offset
, padding
, ENC_NA
);
1637 /* PARTIAL DISSECTOR ROUTINES
1638 these routines are called by dissect_pcp_message_* as needed
1641 static int dissect_pcp_partial_pmid(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
)
1643 proto_item
*pcp_pmid_item
;
1644 proto_tree
*pcp_pmid_tree
;
1645 uint32_t bits_offset
;
1649 bits_offset
= offset
* 8;
1651 pmid
= tvb_get_ntohl(tvb
, offset
);
1652 name
= get_name_from_pmid(pmid
, pinfo
);
1654 /* subtree for pmid */
1655 pcp_pmid_item
= proto_tree_add_item(tree
, hf_pcp_pmid
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1656 proto_item_append_text(pcp_pmid_item
, " (%s)", name
);
1657 pcp_pmid_tree
= proto_item_add_subtree(pcp_pmid_item
, ett_pcp
);
1660 proto_tree_add_bits_item(pcp_pmid_tree
, hf_pcp_pmid_flag
, tvb
, bits_offset
, 1, ENC_BIG_ENDIAN
);
1662 /* domain - 9 bits */
1663 proto_tree_add_bits_item(pcp_pmid_tree
, hf_pcp_pmid_domain
, tvb
, bits_offset
, 9, ENC_BIG_ENDIAN
);
1665 /* cluster - 12 bits */
1666 proto_tree_add_bits_item(pcp_pmid_tree
, hf_pcp_pmid_cluster
, tvb
, bits_offset
, 12, ENC_BIG_ENDIAN
);
1668 /* item - 10 bits */
1669 proto_tree_add_bits_item(pcp_pmid_tree
, hf_pcp_pmid_item
, tvb
, bits_offset
, 10, ENC_BIG_ENDIAN
);
1675 static int dissect_pcp_partial_when(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
, int offset
)
1677 proto_item
*pcp_when_item
;
1678 proto_tree
*pcp_when_tree
;
1680 /* when - create a new subtree for each val */
1681 pcp_when_item
= proto_tree_add_item(tree
, hf_pcp_when
, tvb
, offset
, 8, ENC_NA
);
1682 pcp_when_tree
= proto_item_add_subtree(pcp_when_item
, ett_pcp
);
1685 proto_tree_add_item(pcp_when_tree
, hf_pcp_when_sec
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1688 proto_tree_add_item(pcp_when_tree
, hf_pcp_when_usec
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1694 static int dissect_pcp_partial_features(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
)
1696 uint16_t feature_flags
;
1697 const char *feature_flags_string
;
1699 static int * const pcp_feature_flags_header_fields
[] = {
1700 &hf_pcp_features_flags_labels
,
1701 &hf_pcp_features_flags_bad_label
,
1702 &hf_pcp_features_flags_cert_reqd
,
1703 &hf_pcp_features_flags_container
,
1704 &hf_pcp_features_flags_no_nss_init
,
1705 &hf_pcp_features_flags_secure_ack
,
1706 &hf_pcp_features_flags_creds_reqd
,
1707 &hf_pcp_features_flags_auth
,
1708 &hf_pcp_features_flags_compress
,
1709 &hf_pcp_features_flags_secure
,
1713 feature_flags
= tvb_get_ntohs(tvb
, offset
);
1714 feature_flags_string
= get_pcp_features_to_string(pinfo
->pool
, feature_flags
);
1716 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " Features=[%s]", feature_flags_string
);
1718 proto_tree_add_bitmask(tree
, tvb
, offset
, hf_pcp_features_flags
, ett_pcp_start_features
, pcp_feature_flags_header_fields
, ENC_BIG_ENDIAN
);
1721 if ((feature_flags
& PCP_PDU_FLAG_LABELS
) == PCP_PDU_FLAG_LABELS
&& server_to_client(pinfo
)) {
1722 pcp_conv_info_t
*pcp_conv_info
= get_pcp_conversation_info(pinfo
);
1723 pcp_conv_info
->using_good_labels
= true;
1729 static int dissect_pcp_partial_labelset(tvbuff_t
*tvb
, proto_tree
*tree
, packet_info
*pinfo
, int offset
)
1731 proto_item
*pcp_label_sets_item
= proto_tree_add_item(tree
, hf_pcp_label_sets
, tvb
, offset
, -1, ENC_NA
);
1732 proto_tree
*pcp_label_sets_tree
= proto_item_add_subtree(pcp_label_sets_item
, ett_pcp
);
1735 proto_tree_add_item(pcp_label_sets_tree
, hf_pcp_label_sets_inst
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1738 /* Number of labels or error */
1739 int32_t nlabels_or_error
= tvb_get_ntohl(tvb
, offset
);
1740 proto_tree_add_item(pcp_label_sets_tree
, hf_pcp_label_sets_nlabels
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1742 if (nlabels_or_error
< 0) {
1743 expert_add_info(pinfo
, pcp_label_sets_tree
, &ei_pcp_label_error
);
1746 /* Offset to start of JSON */
1747 uint32_t json_start_offset
= tvb_get_ntohl(tvb
, offset
);
1748 proto_tree_add_item(pcp_label_sets_tree
, hf_pcp_label_sets_json
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1751 /* Length of JSON string */
1752 proto_tree_add_item(pcp_label_sets_tree
, hf_pcp_label_sets_jsonlen
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1756 for (int i
= 0; i
< nlabels_or_error
; i
++) {
1757 offset
= dissect_pcp_partial_label(tvb
, pinfo
, pcp_label_sets_tree
, offset
, json_start_offset
);
1760 /* Fix up end length */
1761 proto_item_set_end(pcp_label_sets_item
, tvb
, offset
);
1767 static int dissect_pcp_partial_label(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
, uint32_t json_start_offset
)
1769 proto_item
*pcp_label_sets_label_item
= proto_tree_add_item(tree
, hf_pcp_label_sets_labels
, tvb
, offset
, -1, ENC_NA
);
1770 proto_tree
*pcp_label_sets_label_tree
= proto_item_add_subtree(pcp_label_sets_label_item
, ett_pcp
);
1773 uint16_t name_offset
= tvb_get_uint16(tvb
, offset
, ENC_BIG_ENDIAN
);
1774 proto_tree_add_item(pcp_label_sets_label_tree
, hf_pcp_label_sets_labels_nameoffset
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
1778 uint32_t name_length
= tvb_get_uint8(tvb
, offset
);
1779 proto_tree_add_item(pcp_label_sets_label_tree
, hf_pcp_label_sets_labels_namelen
, tvb
, offset
, 1, ENC_NA
);
1783 proto_tree_add_item(pcp_label_sets_label_tree
, hf_pcp_label_sets_labels_flags
, tvb
, offset
, 1, ENC_NA
);
1787 uint16_t value_offset
= tvb_get_uint16(tvb
, offset
, ENC_BIG_ENDIAN
);
1788 proto_tree_add_item(pcp_label_sets_label_tree
, hf_pcp_label_sets_labels_valueoffset
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
1792 uint16_t value_length
= tvb_get_uint16(tvb
, offset
, ENC_BIG_ENDIAN
);
1793 /* Value length was not correctly converted to network-byte order in pcp v4.0.0-v4.0.1, it was encoded with whatever
1794 * byte order the host uses. We try and pick this up and accommodate either by detecting the feature off the START PDU
1795 * and failing that, check if the offset+length would be greater than the length of the captured packets. This isn't
1796 * exhaustive but there is not much else to do apart from _only_ dissecting the known good LABEL PDUs.
1798 if(is_using_good_labels(pinfo
)) {
1799 proto_tree_add_item(pcp_label_sets_label_tree
, hf_pcp_label_sets_labels_valuelen
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
1801 else if(label_value_length_looks_like_wrong_endianness(tvb
, value_offset
, value_length
)) {
1802 /* We're _probably_ using the wrong endianness but we didn't capture the initial exchange to find out */
1803 value_length
= tvb_get_uint16(tvb
, offset
, ENC_LITTLE_ENDIAN
);
1804 proto_tree_add_item(pcp_label_sets_label_tree
, hf_pcp_label_sets_labels_valuelen
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1805 expert_add_info(pinfo
, pcp_label_sets_label_tree
, &ei_pcp_label_error_endianness
);
1807 proto_tree_add_item(pcp_label_sets_label_tree
, hf_pcp_label_sets_labels_valuelen
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
1808 expert_add_info(pinfo
, pcp_label_sets_label_tree
, &ei_pcp_label_error_endianness
);
1813 proto_tree_add_item(pcp_label_sets_label_tree
, hf_pcp_label_sets_labels_name
, tvb
, json_start_offset
+ name_offset
, name_length
, ENC_ASCII
| ENC_NA
);
1816 proto_tree_add_item(pcp_label_sets_label_tree
, hf_pcp_label_sets_labels_value
, tvb
, json_start_offset
+ value_offset
, value_length
, ENC_ASCII
| ENC_NA
);
1818 /* Add to subtree */
1819 uint8_t *name
= tvb_get_string_enc(pinfo
->pool
, tvb
, json_start_offset
+ name_offset
, name_length
, ENC_ASCII
| ENC_NA
);
1820 uint8_t *value
= tvb_get_string_enc(pinfo
->pool
, tvb
, json_start_offset
+ value_offset
, value_length
, ENC_ASCII
| ENC_NA
);
1821 proto_item_append_text(pcp_label_sets_label_item
, " (%s:%s)", name
, value
);
1823 proto_item_set_end(pcp_label_sets_label_item
, tvb
, offset
);
1828 static bool is_using_good_labels(packet_info
*pinfo
)
1830 /* Try to establish if we've got good labels from an earlier START PDU */
1831 return get_pcp_conversation_info(pinfo
)->using_good_labels
;
1834 static bool label_value_length_looks_like_wrong_endianness(tvbuff_t
*tvb
, uint16_t value_offset
, uint16_t value_length
)
1836 /* Try to detect if the offset + length is greater than the TVB length which may happen with a
1837 * wrongly-encoded endianness. This may fail in some cases if the label is early on in the frame and has
1838 * many other labels that wouldn't push it over of the TVB length.
1840 return tvb_reported_length(tvb
) < ((unsigned)value_offset
+ (unsigned)value_length
);
1843 /* MAIN DISSECTING ROUTINE (after passed from dissect_tcp, all non-ssl packets hit function) */
1844 static int dissect_pcp_message(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
1846 proto_item
*root_pcp_item
;
1847 proto_tree
*pcp_tree
;
1848 conversation_t
*conversation
;
1849 pcp_conv_info_t
*pcp_conv_info
;
1850 uint32_t packet_type
;
1854 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "PCP");
1855 col_clear(pinfo
->cinfo
, COL_INFO
);
1858 conversation
= find_or_create_conversation(pinfo
);
1860 pcp_conv_info
= (pcp_conv_info_t
*)conversation_get_proto_data(conversation
, proto_pcp
);
1862 if(pcp_conv_info
== NULL
) {
1863 pcp_conv_info
= wmem_new(wmem_file_scope(), pcp_conv_info_t
);
1864 conversation_add_proto_data(conversation
, proto_pcp
, pcp_conv_info
);
1866 pcp_conv_info
->pmid_name_candidates
= wmem_array_new(wmem_file_scope(), sizeof(uint8_t *));
1867 pcp_conv_info
->pmid_to_name
= wmem_map_new(wmem_file_scope(), g_direct_hash
, g_direct_equal
);
1868 pcp_conv_info
->last_pmns_names_frame
= 0;
1869 pcp_conv_info
->last_processed_pmns_names_frame
= 0;
1870 pcp_conv_info
->using_good_labels
= false;
1873 root_pcp_item
= proto_tree_add_item(tree
, proto_pcp
, tvb
, 0, -1, ENC_NA
);
1874 pcp_tree
= proto_item_add_subtree(root_pcp_item
, ett_pcp
);
1876 packet_type
= tvb_get_ntohl(tvb
, 4);
1878 /* check if we are the client requesting or the server */
1879 if (server_to_client(pinfo
)) {
1880 col_set_str(pinfo
->cinfo
, COL_INFO
, "Server > Client ");
1882 col_set_str(pinfo
->cinfo
, COL_INFO
, "Client > Server ");
1885 /* PCP packet length */
1886 proto_tree_add_item(pcp_tree
, hf_pcp_pdu_length
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1888 /* PCP Packet type */
1889 proto_tree_add_item(pcp_tree
, hf_pcp_pdu_type
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1891 /* PCP Remote PID */
1892 proto_tree_add_item(pcp_tree
, hf_pcp_pdu_pid
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1895 /* dissect the rest of the packet depending on the type */
1896 switch (packet_type
) {
1898 dissect_pcp_message_creds(tvb
, pinfo
, pcp_tree
, offset
);
1901 case PCP_PDU_START_OR_ERROR
:
1902 err_bytes
= tvb_get_ntohl(tvb
, offset
); /* get the first 4 bytes, determine if this is an error or not */
1903 /* errors are signed and are all negative so check for a negative number.
1904 It's the only way we can differentiate between start/error packets */
1905 if (err_bytes
< 0) {
1906 dissect_pcp_message_error(tvb
, pinfo
, pcp_tree
, offset
);
1908 dissect_pcp_message_start(tvb
, pinfo
, pcp_tree
, offset
);
1912 case PCP_PDU_PMNS_TRAVERSE
:
1913 dissect_pcp_message_pmns_traverse(tvb
, pinfo
, pcp_tree
, offset
);
1916 case PCP_PDU_PMNS_NAMES
:
1917 dissect_pcp_message_pmns_names(tvb
, pinfo
, pcp_tree
, offset
);
1920 case PCP_PDU_PMNS_CHILD
:
1921 dissect_pcp_message_pmns_child(tvb
, pinfo
, pcp_tree
, offset
);
1924 case PCP_PDU_PMNS_IDS
:
1925 dissect_pcp_message_pmns_ids(tvb
, pinfo
, pcp_tree
, offset
);
1928 case PCP_PDU_PROFILE
:
1929 dissect_pcp_message_profile(tvb
, pinfo
, pcp_tree
, offset
);
1933 dissect_pcp_message_fetch(tvb
, pinfo
, pcp_tree
, offset
);
1936 case PCP_PDU_RESULT
:
1937 dissect_pcp_message_result(tvb
, pinfo
, pcp_tree
, offset
);
1940 case PCP_PDU_DESC_REQ
:
1941 dissect_pcp_message_desc_req(tvb
, pinfo
, pcp_tree
, offset
);
1945 dissect_pcp_message_desc(tvb
, pinfo
, pcp_tree
, offset
);
1948 case PCP_PDU_INSTANCE_REQ
:
1949 dissect_pcp_message_instance_req(tvb
, pinfo
, pcp_tree
, offset
);
1952 case PCP_PDU_INSTANCE
:
1953 dissect_pcp_message_instance(tvb
, pinfo
, pcp_tree
, offset
);
1956 case PCP_PDU_TEXT_REQ
:
1957 dissect_pcp_message_text_req(tvb
, pinfo
, pcp_tree
, offset
);
1961 dissect_pcp_message_text(tvb
, pinfo
, pcp_tree
, offset
);
1964 case PCP_PDU_USER_AUTH
:
1965 dissect_pcp_message_user_auth(tvb
, pinfo
, pcp_tree
, offset
);
1968 case PCP_PDU_LABEL_REQ
:
1969 dissect_pcp_message_label_req(tvb
, pinfo
, pcp_tree
, offset
);
1973 dissect_pcp_message_label(tvb
, pinfo
, pcp_tree
, offset
);
1977 /* append the type of packet */
1978 col_append_str(pinfo
->cinfo
, COL_INFO
, "[UNIMPLEMENTED TYPE]");
1979 /* if we got here, then we didn't get a packet type that we know of */
1980 expert_add_info(pinfo
, pcp_tree
, &ei_pcp_unimplemented_packet_type
);
1983 return tvb_captured_length(tvb
);
1986 static int dissect_pcp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data
)
1988 /* pass all packets through TCP-reassembly */
1989 tcp_dissect_pdus(tvb
, pinfo
, tree
, true, PCP_HEADER_LEN
, get_pcp_message_len
, dissect_pcp_message
, data
);
1990 return tvb_captured_length(tvb
);
1993 /* setup the dissecting */
1994 void proto_register_pcp(void)
1996 static hf_register_info hf
[] = {
1997 { &hf_pcp_pdu_length
,
1998 { "PDU Length", "pcp.length",
1999 FT_UINT32
, BASE_DEC
,
2005 { "Type", "pcp.type",
2006 FT_UINT32
, BASE_HEX
,
2007 VALS(packettypenames
), 0x0,
2012 { "From", "pcp.from",
2013 FT_UINT32
, BASE_DEC
,
2018 { &hf_pcp_pdu_error
,
2019 { "Error", "pcp.error",
2021 VALS(packettypenames_errors
), 0x0,
2025 { &hf_pcp_pdu_padding
,
2026 { "Padding", "pcp.padding",
2032 { &hf_pcp_creds_number_of
,
2033 { "Number of Credentials", "pcp.creds.number",
2034 FT_UINT32
, BASE_DEC
,
2039 { &hf_pcp_creds_type
,
2040 { "Credentials Type", "pcp.creds.type",
2042 VALS(packettypenames_creds
), 0x0,
2046 { &hf_pcp_creds_version
,
2047 { "Credentials Version", "pcp.creds.version",
2054 { "Start", "pcp.start",
2060 { &hf_pcp_start_zero
,
2061 { "Start Bit", "pcp.start.zero",
2063 TFS(&tfs_set_notset
), 0x80,
2067 { &hf_pcp_start_version
,
2068 { "Version", "pcp.start.version",
2069 FT_UINT8
, BASE_DEC
, /* not a real 8 bit int, only uses 7 bits */
2074 { &hf_pcp_start_status
,
2075 { "Start Status", "pcp.start.status",
2076 FT_UINT32
, BASE_DEC
,
2081 { &hf_pcp_start_licensed
,
2082 { "Licensed", "pcp.start.licensed",
2088 { &hf_pcp_features_flags
,
2089 { "Features", "pcp.features.flags",
2090 FT_UINT16
, BASE_HEX
,
2095 { &hf_pcp_features_flags_secure
,
2096 { "Secure", "pcp.features.flags.secure",
2098 TFS(&tfs_set_notset
), PCP_PDU_FLAG_SECURE
,
2102 { &hf_pcp_features_flags_compress
,
2103 { "Compression", "pcp.features.flags.compression",
2105 TFS(&tfs_set_notset
), PCP_PDU_FLAG_COMPRESS
,
2109 { &hf_pcp_features_flags_auth
,
2110 { "Authentication", "pcp.features.flags.auth",
2112 TFS(&tfs_set_notset
), PCP_PDU_FLAG_AUTH
,
2116 { &hf_pcp_features_flags_creds_reqd
,
2117 { "Credentials Required", "pcp.features.flags.creds_reqd",
2119 TFS(&tfs_set_notset
), PCP_PDU_FLAG_CREDS_REQD
,
2123 { &hf_pcp_features_flags_secure_ack
,
2124 { "Secure Acknowledgement", "pcp.features.flags.secure_ack",
2126 TFS(&tfs_set_notset
), PCP_PDU_FLAG_SECURE_ACK
,
2130 { &hf_pcp_features_flags_no_nss_init
,
2131 { "No NSS Init", "pcp.features.flags.no_nss_init",
2133 TFS(&tfs_set_notset
), PCP_PDU_FLAG_NO_NSS_INIT
,
2137 { &hf_pcp_features_flags_container
,
2138 { "Container", "pcp.features.flags.container",
2140 TFS(&tfs_set_notset
), PCP_PDU_FLAG_CONTAINER
,
2144 { &hf_pcp_features_flags_cert_reqd
,
2145 { "Certificate Required", "pcp.features.flags.cert_reqd",
2147 TFS(&tfs_set_notset
), PCP_PDU_FLAG_CERT_REQD
,
2151 { &hf_pcp_features_flags_bad_label
,
2152 { "Bad Label", "pcp.features.flags.bad_label",
2154 TFS(&tfs_set_notset
), PCP_PDU_FLAG_BAD_LABEL
,
2155 "Legacy label support. Incorrectly implemented in pcp v4.0.0-v4.0.1", HFILL
2158 { &hf_pcp_features_flags_labels
,
2159 { "Labels", "pcp.features.flags.labels",
2161 TFS(&tfs_set_notset
), PCP_PDU_FLAG_LABELS
,
2165 { &hf_pcp_pmns_traverse
,
2166 { "PMNS Traverse", "pcp.pmns_traverse",
2172 { &hf_pcp_pmns_subtype
,
2173 { "Subtype", "pcp.pmns.subtype",
2174 FT_UINT32
, BASE_DEC
,
2179 { &hf_pcp_pmns_namelen
,
2180 { "Name Length", "pcp.pmns.namelen",
2181 FT_UINT32
, BASE_DEC
,
2186 { &hf_pcp_pmns_name
,
2187 { "Name", "pcp.pmns.name",
2188 FT_STRING
, BASE_NONE
,
2193 { &hf_pcp_pmns_names
,
2194 { "PMNS Names", "pcp.pmns_names",
2200 { &hf_pcp_pmns_names_nstrbytes
,
2201 { "String Bytes", "pcp.pmns_names.nstrbytes",
2202 FT_UINT32
, BASE_DEC
,
2207 { &hf_pcp_pmns_names_numstatus
,
2208 { "Status", "pcp.pmns_names.numstatus",
2209 FT_UINT32
, BASE_DEC
,
2214 { &hf_pcp_pmns_names_numnames
,
2215 { "Number of Names", "pcp.pmns_names.numnames",
2216 FT_UINT32
, BASE_DEC
,
2221 { &hf_pcp_pmns_names_nametree
,
2222 { "Names", "pcp.pmns_names.nametree",
2228 { &hf_pcp_pmns_names_nametree_status
,
2229 { "Status", "pcp.pmns_names.nametree.status",
2230 FT_UINT32
, BASE_DEC
,
2235 { &hf_pcp_pmns_names_nametree_namelen
,
2236 { "Length", "pcp.pmns_names.nametree.namelen",
2237 FT_UINT32
, BASE_DEC
,
2242 { &hf_pcp_pmns_names_nametree_name
,
2243 { "Name", "pcp.pmns_names.nametree.name",
2244 FT_STRING
, BASE_NONE
,
2250 { "PMNS IDs", "pcp.pmns_ids",
2256 { &hf_pcp_pmns_ids_status
,
2257 { "Status", "pcp.pmns_ids.status",
2258 FT_UINT32
, BASE_DEC
,
2263 { &hf_pcp_pmns_ids_numids
,
2264 { "Number of IDs", "pcp.pmns_ids.numids",
2265 FT_UINT32
, BASE_DEC
,
2270 { &hf_pcp_pmns_child
,
2271 { "PMID Child", "pcp.pmns.child",
2278 { "PMID", "pcp.pmid",
2279 FT_UINT32
, BASE_DEC
,
2284 { &hf_pcp_pmid_flag
,
2285 { "Flag", "pcp.pmid.flag",
2286 FT_BOOLEAN
, BASE_NONE
,
2291 { &hf_pcp_pmid_domain
,
2292 { "Domain", "pcp.pmid.domain",
2293 FT_UINT16
, BASE_DEC
, /* uses 9 bits */
2298 { &hf_pcp_pmid_cluster
,
2299 { "Cluster", "pcp.pmid.cluster",
2300 FT_UINT16
, BASE_DEC
, /* uses 12 bits */
2305 { &hf_pcp_pmid_item
,
2306 { "Item", "pcp.pmid.item",
2307 FT_UINT16
, BASE_DEC
, /* uses 10 bits */
2312 { &hf_pcp_pmid_type
,
2313 { "Type", "pcp.pmid.type",
2315 VALS(packettypenames_pm_types
), 0x0,
2320 { "Type Semantics", "pcp.pmid.sem",
2321 FT_UINT32
, BASE_DEC
,
2322 VALS(packettypenames_pm_types_sem
), 0x0,
2326 { &hf_pcp_pmid_inst
,
2327 { "Instance", "pcp.pmid.inst",
2328 FT_UINT32
, BASE_DEC
,
2334 { "Profile", "pcp.profile",
2341 { "Context Number", "pcp.ctxnum",
2342 FT_UINT32
, BASE_DEC
,
2347 { &hf_pcp_profile_g_state
,
2348 { "Global Include/Exclude State", "pcp.profile.g_state",
2349 FT_UINT32
, BASE_DEC
,
2354 { &hf_pcp_profile_numprof
,
2355 { "Number of Profiles", "pcp.profile.numprof",
2356 FT_UINT32
, BASE_DEC
,
2361 { &hf_pcp_profile_profile
,
2362 { "Each Profile", "pcp.profile.profile",
2368 { &hf_pcp_profile_profile_state
,
2369 { "Include/Exclude State", "pcp.profile.profile.state",
2370 FT_UINT32
, BASE_DEC
,
2375 { &hf_pcp_profile_profile_numinst
,
2376 { "Number Instances to Follow", "pcp.profile.profile.numinst",
2377 FT_UINT32
, BASE_DEC
,
2383 { "Fetch", "pcp.fetch",
2389 { &hf_pcp_fetch_numpmid
,
2390 { "Number PMIDs", "pcp.fetch.numpmid",
2391 FT_UINT32
, BASE_DEC
,
2397 { "Time Value", "pcp.when",
2404 { "Seconds", "pcp.when.sec",
2405 FT_UINT32
, BASE_DEC
,
2410 { &hf_pcp_when_usec
,
2411 { "Microseconds", "pcp.when.usec",
2412 FT_UINT32
, BASE_DEC
,
2418 { "Description Request", "pcp.desc_req",
2425 { "Description Response", "pcp.desc",
2432 { "PMID Units", "pcp.units",
2438 { &hf_pcp_units_dimspace
,
2439 { "Dimension Space", "pcp.units.dimspace",
2445 { &hf_pcp_units_dimtime
,
2446 { "Dimension Time", "pcp.units.dimtime",
2452 { &hf_pcp_units_dimcount
,
2453 { "Dimension Count", "pcp.units.dimcount",
2459 { &hf_pcp_units_scalespace
,
2460 { "Scale Space", "pcp.units.scalespace",
2462 VALS(packettypenames_pm_units_space
), 0x0,
2466 { &hf_pcp_units_scaletime
,
2467 { "Scale Time", "pcp.units.scaletime",
2469 VALS(packettypenames_pm_units_time
), 0x0,
2473 { &hf_pcp_units_scalecount
,
2474 { "Scale Count", "pcp.units.scalecount",
2480 { &hf_pcp_instance_req
,
2481 { "Instance Request", "pcp.instance_req",
2487 { &hf_pcp_instances
,
2488 { "Instance Response", "pcp.instances",
2494 { &hf_pcp_instances_numinst
,
2495 { "Number of Instances", "pcp.instance_resp.numinst",
2496 FT_UINT32
, BASE_DEC
,
2502 { "Instance", "pcp.instance",
2508 { &hf_pcp_instance_namelen
,
2509 { "Name Length", "pcp.instance.namelen",
2510 FT_UINT32
, BASE_DEC
,
2515 { &hf_pcp_instance_name
,
2516 { "Name", "pcp.instance.name",
2517 FT_STRING
, BASE_NONE
,
2522 { &hf_pcp_instance_indom
,
2523 { "Instance Domain", "pcp.instance.indom",
2524 FT_UINT32
, BASE_DEC
,
2529 { &hf_pcp_instance_valoffset
,
2530 { "Instance Offset", "pcp.instance.valoffset",
2531 FT_UINT32
, BASE_DEC
,
2536 { &hf_pcp_instance_vallength
,
2537 { "Instance Value Length", "pcp.instance.vallength",
2543 { &hf_pcp_instance_value_insitu
,
2544 { "Instance Value", "pcp.instance.value.uint",
2545 FT_UINT32
, BASE_DEC
,
2550 { &hf_pcp_instance_value_ptr
,
2551 { "Instance Value", "pcp.instance.value.string",
2552 FT_STRING
, BASE_NONE
,
2557 { &hf_pcp_instance_value_int
,
2558 { "Instance Value", "pcp.instance.value.int",
2564 { &hf_pcp_instance_value_uint
,
2565 { "Instance Value", "pcp.instance.value.uint",
2566 FT_UINT32
, BASE_DEC
,
2571 { &hf_pcp_instance_value_int64
,
2572 { "Instance Value", "pcp.instance.value.int64",
2578 { &hf_pcp_instance_value_uint64
,
2579 { "Instance Value", "pcp.instance.value.uint64",
2580 FT_UINT64
, BASE_DEC
,
2585 { &hf_pcp_instance_value_float
,
2586 { "Instance Value", "pcp.instance.value.float",
2587 FT_FLOAT
, BASE_NONE
,
2592 { &hf_pcp_instance_value_double
,
2593 { "Instance Value", "pcp.instance.value.float",
2594 FT_DOUBLE
, BASE_NONE
,
2599 { &hf_pcp_instance_value_aggr
,
2600 { "Instance Value", "pcp.instance.value.bytes",
2601 FT_BYTES
, BASE_NONE
,
2607 { "Fetch Results", "pcp.results",
2613 { &hf_pcp_results_numpmid
,
2614 { "Number of PMIDs", "pcp.results.numpmid",
2615 FT_UINT32
, BASE_DEC
,
2621 { "Result", "pcp.result",
2627 { &hf_pcp_result_numval
,
2628 { "Number of Values", "pcp.result.numval",
2629 FT_UINT32
, BASE_DEC
,
2634 { &hf_pcp_result_valfmt
,
2635 { "Value Encoding Format", "pcp.result.valfmt",
2636 FT_UINT32
, BASE_DEC
,
2637 VALS(packettypenames_valfmt
), 0x0,
2642 { "Text Request", "pcp.text_req",
2648 { &hf_pcp_text_type
,
2649 { "Help Text Type", "pcp.text.type",
2655 { &hf_pcp_text_type_format
,
2656 { "Text Type Format", "pcp.text.type.format",
2658 VALS(packettypenames_text_type_format
), 0x0,
2662 { &hf_pcp_text_type_ident
,
2663 { "Text Type Ident", "pcp.text.type.ident",
2665 VALS(packettypenames_text_type_ident
), 0x0,
2670 { "Text Response", "pcp.text",
2676 { &hf_pcp_text_ident
,
2677 { "Text Ident (raw)", "pcp.text.ident",
2678 FT_UINT32
, BASE_DEC
,
2683 { &hf_pcp_text_buflen
,
2684 { "Text Buffer Length", "pcp.text.buflen",
2685 FT_UINT32
, BASE_DEC
,
2690 { &hf_pcp_text_buffer
,
2691 { "Text Buffer", "pcp.text.buffer",
2692 FT_STRING
, BASE_NONE
,
2697 { &hf_pcp_user_auth_payload
,
2698 { "User Authentication Payload", "pcp.user_auth_payload",
2704 { &hf_pcp_label_req
,
2705 { "Label Request", "pcp.label_req",
2711 { &hf_pcp_label_ident
,
2712 { "Label Ident", "pcp.label.ident",
2715 "Domain, PMID or pmInDom identifier", HFILL
2718 { &hf_pcp_label_type
,
2719 { "Label Type", "pcp.label.type",
2721 VALS(packettypenames_label_req_type
), 0x0,
2726 { "Labels", "pcp.label",
2732 { &hf_pcp_label_padding
,
2733 { "Padding", "pcp.label.padding",
2739 { &hf_pcp_label_nsets
,
2740 { "Num Label Sets", "pcp.label.nsets",
2743 "Number of Label Sets", HFILL
2746 { &hf_pcp_label_sets
,
2747 { "Label Set", "pcp.label.sets",
2753 { &hf_pcp_label_sets_inst
,
2754 { "Instance", "pcp.label.sets.inst",
2757 "Instance identifier or PM_IN_NULL", HFILL
2760 { &hf_pcp_label_sets_nlabels
,
2761 { "Num of Labels", "pcp.label.sets.nlabels",
2764 "Number of labels or error code", HFILL
2767 { &hf_pcp_label_sets_json
,
2768 { "JSON Offset", "pcp.label.sets.json",
2771 "Offset to start of JSON string", HFILL
2774 { &hf_pcp_label_sets_jsonlen
,
2775 { "JSON Length", "pcp.label.sets.jsonlen",
2778 "Length of bytes of the JSON string", HFILL
2781 { &hf_pcp_label_sets_labels
,
2782 { "Label", "pcp.label.sets.label",
2788 { &hf_pcp_label_sets_labels_nameoffset
,
2789 { "Name Offset", "pcp.label.sets.label.nameoffset",
2792 "Label name offset in the JSONB string", HFILL
2795 { &hf_pcp_label_sets_labels_namelen
,
2796 { "Name Length", "pcp.label.sets.label.namelen",
2799 "Length of name excluding NULL terminator", HFILL
2802 { &hf_pcp_label_sets_labels_flags
,
2803 { "Flags", "pcp.label.sets.label.flags",
2806 "Information about this label", HFILL
2809 { &hf_pcp_label_sets_labels_valueoffset
,
2810 { "Value Offset", "pcp.label.sets.label.valueoffset",
2813 "Offset of the label value", HFILL
2816 { &hf_pcp_label_sets_labels_valuelen
,
2817 { "Value Length", "pcp.label.sets.label.valuelen",
2820 "Length of the value in bytes", HFILL
2823 { &hf_pcp_label_sets_labels_name
,
2824 { "Name", "pcp.label.sets.label.name",
2825 FT_STRING
, BASE_NONE
,
2830 { &hf_pcp_label_sets_labels_value
,
2831 { "Value", "pcp.label.sets.label.value",
2832 FT_STRING
, BASE_NONE
,
2834 "Label value", HFILL
2841 static int *ett
[] = {
2843 &ett_pcp_pdu_length
,
2847 &ett_pcp_pdu_padding
,
2848 &ett_pcp_creds_number_of
,
2849 &ett_pcp_creds_type
,
2850 &ett_pcp_creds_vala
,
2851 &ett_pcp_creds_valb
,
2852 &ett_pcp_creds_valc
,
2854 &ett_pcp_start_status
,
2855 &ett_pcp_start_zero
,
2856 &ett_pcp_start_version
,
2857 &ett_pcp_start_licensed
,
2858 &ett_pcp_start_features
,
2859 &ett_pcp_pmns_traverse
,
2860 &ett_pcp_pmns_subtype
,
2861 &ett_pcp_pmns_namelen
,
2863 &ett_pcp_pmns_names
,
2864 &ett_pcp_pmns_names_nstrbytes
,
2865 &ett_pcp_pmns_names_numstatus
,
2866 &ett_pcp_pmns_names_numnames
,
2867 &ett_pcp_pmns_names_nametree
,
2868 &ett_pcp_pmns_names_nametree_status
,
2869 &ett_pcp_pmns_names_nametree_namelen
,
2870 &ett_pcp_pmns_names_nametree_name
,
2872 &ett_pcp_pmns_ids_status
,
2873 &ett_pcp_pmns_ids_numids
,
2874 &ett_pcp_pmns_child
,
2877 &ett_pcp_pmid_domain
,
2878 &ett_pcp_pmid_cluster
,
2884 &ett_pcp_profile_g_state
,
2885 &ett_pcp_profile_numprof
,
2886 &ett_pcp_profile_profile
,
2887 &ett_pcp_profile_profile_state
,
2888 &ett_pcp_profile_profile_numinst
,
2890 &ett_pcp_fetch_numpmid
,
2896 &ett_pcp_units_dimspace
,
2897 &ett_pcp_units_dimtime
,
2898 &ett_pcp_units_dimcount
,
2899 &ett_pcp_units_scalespace
,
2900 &ett_pcp_units_scaletime
,
2901 &ett_pcp_units_scalecount
,
2903 &ett_pcp_instance_req
,
2904 &ett_pcp_instance_namelen
,
2905 &ett_pcp_instance_name
,
2906 &ett_pcp_instance_indom
,
2907 &ett_pcp_instance_inst
,
2908 &ett_pcp_instance_valoffset
,
2909 &ett_pcp_instance_vallength
,
2910 &ett_pcp_instance_value_insitu
,
2911 &ett_pcp_instance_value_ptr
,
2912 &ett_pcp_instance_value_int
,
2913 &ett_pcp_instance_value_uint
,
2914 &ett_pcp_instance_value_int64
,
2915 &ett_pcp_instance_value_uint64
,
2916 &ett_pcp_instance_value_float
,
2917 &ett_pcp_instance_value_double
,
2918 &ett_pcp_instance_value_aggr
,
2920 &ett_pcp_instances_numinst
,
2922 &ett_pcp_results_numpmid
,
2924 &ett_pcp_result_numval
,
2925 &ett_pcp_result_valfmt
,
2928 &ett_pcp_text_type_format
,
2929 &ett_pcp_text_type_ident
,
2931 &ett_pcp_text_ident
,
2932 &ett_pcp_text_buflen
,
2933 &ett_pcp_text_buffer
,
2936 static ei_register_info ei
[] = {
2937 { &ei_pcp_type_event_unimplemented
, { "pcp.pmid.type.event.unimplemented", PI_UNDECODED
, PI_WARN
, "PM_TYPE_EVENT: Unimplemented Value Type", EXPFILL
}},
2938 { &ei_pcp_type_nosupport_unsupported
, { "pcp.pmid.type.nosupport.unsupported", PI_UNDECODED
, PI_WARN
, "PM_TYPE_NOSUPPORT: Unsupported Value Type", EXPFILL
}},
2939 { &ei_pcp_type_unknown_unknown_value
, { "pcp.pmid.type.unknown.unknown_value", PI_UNDECODED
, PI_WARN
, "PM_TYPE_UNKNOWN: Unknown Value Type", EXPFILL
}},
2940 { &ei_pcp_unimplemented_value
, { "pcp.pmid.type.unimplemented", PI_UNDECODED
, PI_WARN
, "Unimplemented Value Type", EXPFILL
}},
2941 { &ei_pcp_unimplemented_packet_type
, { "pcp.type.unimplemented", PI_UNDECODED
, PI_WARN
, "Unimplemented Packet Type", EXPFILL
}},
2942 { &ei_pcp_ssl_upgrade
, { "pcp.ssl_upgrade", PI_COMMENTS_GROUP
, PI_COMMENT
, "SSL upgrade via SECURE_ACK", EXPFILL
}},
2943 { &ei_pcp_ssl_upgrade_failed
, { "pcp.ssl_upgrade_failed", PI_RESPONSE_CODE
, PI_WARN
, "SSL upgrade via SECURE_ACK failed", EXPFILL
}},
2944 { &ei_pcp_label_error
, { "pcp.label.error", PI_RESPONSE_CODE
, PI_NOTE
, "Label returned an error", EXPFILL
}},
2945 { &ei_pcp_label_error_endianness
, { "pcp.label.error.endianness", PI_RESPONSE_CODE
, PI_NOTE
, "Value length has been decoded without knowing the endianness. It has been attempted to be detected but may be wrong", EXPFILL
}},
2948 expert_module_t
* expert_pcp
;
2950 proto_pcp
= proto_register_protocol("Performance Co-Pilot", "PCP", "pcp");
2952 expert_pcp
= expert_register_protocol(proto_pcp
);
2953 expert_register_field_array(expert_pcp
, ei
, array_length(ei
));
2955 proto_register_field_array(proto_pcp
, hf
, array_length(hf
));
2956 proto_register_subtree_array(ett
, array_length(ett
));
2958 pcp_handle
= register_dissector("pcp", dissect_pcp
, proto_pcp
);
2961 void proto_reg_handoff_pcp(void)
2963 dissector_add_uint_with_preference("tcp.port", PCP_PORT
, pcp_handle
);
2967 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2972 * indent-tabs-mode: nil
2975 * vi: set shiftwidth=4 tabstop=8 expandtab:
2976 * :indentSize=4:tabSize=8:noTabs=true: