/src/wireshark/epan/dissectors/packet-ros.c
Line | Count | Source |
1 | | /* Do not modify this file. Changes will be overwritten. */ |
2 | | /* Generated automatically by the ASN.1 to Wireshark dissector compiler */ |
3 | | /* packet-ros.c */ |
4 | | /* asn2wrs.py -b -q -L -p ros -c ./ros.cnf -s ./packet-ros-template -D . -O ../.. ros.asn Remote-Operations-Information-Objects.asn */ |
5 | | |
6 | | /* packet-ros_asn1.c |
7 | | * Routines for ROS packet dissection |
8 | | * Graeme Lunt 2005 |
9 | | * |
10 | | * Wireshark - Network traffic analyzer |
11 | | * By Gerald Combs <gerald@wireshark.org> |
12 | | * Copyright 1998 Gerald Combs |
13 | | * |
14 | | * SPDX-License-Identifier: GPL-2.0-or-later |
15 | | */ |
16 | | |
17 | | #include "config.h" |
18 | | |
19 | | #include <epan/packet.h> |
20 | | #include <epan/conversation.h> |
21 | | #include <epan/asn1.h> |
22 | | #include <epan/expert.h> |
23 | | #include <wsutil/array.h> |
24 | | |
25 | | #include "packet-ber.h" |
26 | | #include "packet-pres.h" |
27 | | #include "packet-ros.h" |
28 | | |
29 | | void proto_register_ros(void); |
30 | | void proto_reg_handoff_ros(void); |
31 | | |
32 | | /* Initialize the protocol and registered fields */ |
33 | | static int proto_ros; |
34 | | |
35 | | static proto_tree *top_tree; |
36 | | static uint32_t opcode; |
37 | | static uint32_t invokeid; |
38 | | |
39 | | static dissector_handle_t ros_handle; |
40 | | |
41 | | typedef struct ros_conv_info_t { |
42 | | wmem_map_t *unmatched; /* unmatched operations */ |
43 | | wmem_map_t *matched; /* matched operations */ |
44 | | } ros_conv_info_t; |
45 | | |
46 | | typedef struct ros_call_response { |
47 | | bool is_request; |
48 | | uint32_t req_frame; |
49 | | nstime_t req_time; |
50 | | uint32_t rep_frame; |
51 | | unsigned invokeId; |
52 | | } ros_call_response_t; |
53 | | |
54 | | static int hf_ros_response_in; |
55 | | static int hf_ros_response_to; |
56 | | static int hf_ros_time; |
57 | | |
58 | | |
59 | | static int hf_ros_invoke; /* Invoke */ |
60 | | static int hf_ros_returnResult; /* ReturnResult */ |
61 | | static int hf_ros_returnError; /* ReturnError */ |
62 | | static int hf_ros_reject; /* T_reject */ |
63 | | static int hf_ros_bind_invoke; /* T_bind_invoke */ |
64 | | static int hf_ros_bind_result; /* T_bind_result */ |
65 | | static int hf_ros_bind_error; /* T_bind_error */ |
66 | | static int hf_ros_unbind_invoke; /* T_unbind_invoke */ |
67 | | static int hf_ros_unbind_result; /* T_unbind_result */ |
68 | | static int hf_ros_unbind_error; /* T_unbind_error */ |
69 | | static int hf_ros_invokeId; /* InvokeId */ |
70 | | static int hf_ros_linkedId; /* INTEGER */ |
71 | | static int hf_ros_opcode; /* OperationCode */ |
72 | | static int hf_ros_argument; /* T_argument */ |
73 | | static int hf_ros_result; /* T_result */ |
74 | | static int hf_ros_operationResult; /* OperationResult */ |
75 | | static int hf_ros_errcode; /* ErrorCode */ |
76 | | static int hf_ros_parameter; /* T_parameter */ |
77 | | static int hf_ros_problem; /* T_problem */ |
78 | | static int hf_ros_general; /* GeneralProblem */ |
79 | | static int hf_ros_invokeProblem; /* InvokeProblem */ |
80 | | static int hf_ros_rejectResult; /* ReturnResultProblem */ |
81 | | static int hf_ros_rejectError; /* ReturnErrorProblem */ |
82 | | static int hf_ros_present; /* T_present */ |
83 | | static int hf_ros_absent; /* NULL */ |
84 | | static int hf_ros_local; /* INTEGER */ |
85 | | static int hf_ros_global; /* OBJECT_IDENTIFIER */ |
86 | | |
87 | | /* Initialize the subtree pointers */ |
88 | | static int ett_ros; |
89 | | static int ett_ros_unknown; |
90 | | static int ett_ros_invoke_argument; |
91 | | static int ett_ros_return_result; |
92 | | static int ett_ros_bind_invoke; |
93 | | static int ett_ros_bind_result; |
94 | | static int ett_ros_bind_error; |
95 | | static int ett_ros_unbind_invoke; |
96 | | static int ett_ros_unbind_result; |
97 | | static int ett_ros_unbind_error; |
98 | | static int ett_ros_ROS; |
99 | | static int ett_ros_Invoke; |
100 | | static int ett_ros_ReturnResult; |
101 | | static int ett_ros_T_result; |
102 | | static int ett_ros_ReturnError; |
103 | | static int ett_ros_Reject; |
104 | | static int ett_ros_T_problem; |
105 | | static int ett_ros_InvokeId; |
106 | | static int ett_ros_Code; |
107 | | |
108 | | static expert_field ei_ros_dissector_oid_not_implemented; |
109 | | static expert_field ei_ros_unknown_ros_pdu; |
110 | | |
111 | | static dissector_table_t ros_oid_dissector_table; |
112 | | |
113 | | static wmem_map_t *protocol_table; |
114 | | |
115 | | void |
116 | | register_ros_oid_dissector_handle(const char *oid, dissector_handle_t dissector, int proto _U_, const char *name, bool uses_rtse) |
117 | 60 | { |
118 | 60 | dissector_add_string("ros.oid", oid, dissector); |
119 | | |
120 | 60 | if(!uses_rtse) |
121 | | /* if we are not using RTSE, then we must register ROS with BER (ACSE) */ |
122 | 45 | register_ber_oid_dissector_handle(oid, ros_handle, proto, name); |
123 | 60 | } |
124 | | |
125 | | void |
126 | | register_ros_protocol_info(const char *oid, const ros_info_t *rinfo, int proto _U_, const char *name, bool uses_rtse) |
127 | 180 | { |
128 | 180 | wmem_map_insert(protocol_table, (void *)oid, (void *)rinfo); |
129 | | |
130 | 180 | if(!uses_rtse) |
131 | | /* if we are not using RTSE, then we must register ROS with BER (ACSE) */ |
132 | 165 | register_ber_oid_dissector_handle(oid, ros_handle, proto, name); |
133 | 180 | } |
134 | | |
135 | | static dissector_t ros_lookup_opr_dissector(int32_t opcode_lcl, const ros_opr_t *operations, bool argument) |
136 | 0 | { |
137 | | /* we don't know what order asn2wrs/module definition is, so ... */ |
138 | 0 | if(operations) { |
139 | 0 | for(;operations->arg_pdu != (dissector_t)(-1); operations++) |
140 | 0 | if(operations->opcode == opcode_lcl) |
141 | 0 | return argument ? operations->arg_pdu : operations->res_pdu; |
142 | |
|
143 | 0 | } |
144 | 0 | return NULL; |
145 | 0 | } |
146 | | |
147 | | static dissector_t ros_lookup_err_dissector(int32_t errcode, const ros_err_t *errors) |
148 | 0 | { |
149 | | /* we don't know what order asn2wrs/module definition is, so ... */ |
150 | 0 | if(errors) { |
151 | 0 | for(;errors->err_pdu != (dissector_t) (-1); errors++) { |
152 | 0 | if(errors->errcode == errcode) |
153 | 0 | return errors->err_pdu; |
154 | 0 | } |
155 | 0 | } |
156 | 0 | return NULL; |
157 | 0 | } |
158 | | |
159 | | |
160 | | static int |
161 | | ros_try_string(const char *oid, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, struct SESSION_DATA_STRUCTURE* session) |
162 | 77 | { |
163 | 77 | ros_info_t *rinfo; |
164 | 77 | int32_t opcode_lcl = 0; |
165 | 77 | const char *opname = NULL; |
166 | 77 | const char *suffix = NULL; |
167 | 77 | dissector_t opdissector = NULL; |
168 | 77 | const value_string *lookup; |
169 | 77 | proto_item *item=NULL; |
170 | 77 | proto_tree *ros_tree=NULL; |
171 | | |
172 | 77 | if((session != NULL) && (oid != NULL) && ((rinfo = (ros_info_t*)wmem_map_lookup(protocol_table, oid)) != NULL)) { |
173 | |
|
174 | 0 | if(tree){ |
175 | 0 | item = proto_tree_add_item(tree, *(rinfo->proto), tvb, 0, -1, ENC_NA); |
176 | 0 | ros_tree = proto_item_add_subtree(item, *(rinfo->ett_proto)); |
177 | 0 | } |
178 | |
|
179 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, rinfo->name); |
180 | | |
181 | | /* if this is a bind operation */ |
182 | 0 | if((session->ros_op & ROS_OP_TYPE_MASK) == ROS_OP_BIND) { |
183 | | /* use the in-built operation codes */ |
184 | 0 | if((session->ros_op & ROS_OP_PDU_MASK) == ROS_OP_ERROR) |
185 | 0 | opcode_lcl = err_ros_bind; |
186 | 0 | else |
187 | 0 | opcode_lcl = op_ros_bind; |
188 | 0 | } else |
189 | | /* otherwise just take the opcode */ |
190 | 0 | opcode_lcl = session->ros_op & ROS_OP_OPCODE_MASK; |
191 | | |
192 | | /* default lookup in the operations */ |
193 | 0 | lookup = rinfo->opr_code_strings; |
194 | |
|
195 | 0 | switch(session->ros_op & ROS_OP_PDU_MASK) { |
196 | 0 | case ROS_OP_ARGUMENT: |
197 | 0 | opdissector = ros_lookup_opr_dissector(opcode_lcl, rinfo->opr_code_dissectors, true); |
198 | 0 | suffix = "_argument"; |
199 | 0 | break; |
200 | 0 | case ROS_OP_RESULT: |
201 | 0 | opdissector = ros_lookup_opr_dissector(opcode_lcl, rinfo->opr_code_dissectors, false); |
202 | 0 | suffix = "_result"; |
203 | 0 | break; |
204 | 0 | case ROS_OP_ERROR: |
205 | 0 | opdissector = ros_lookup_err_dissector(opcode_lcl, rinfo->err_code_dissectors); |
206 | 0 | lookup = rinfo->err_code_strings; |
207 | 0 | break; |
208 | 0 | default: |
209 | 0 | break; |
210 | 0 | } |
211 | | |
212 | 0 | if(opdissector) { |
213 | |
|
214 | 0 | opname = val_to_str(pinfo->pool, opcode_lcl, lookup, "Unknown opcode (%d)"); |
215 | |
|
216 | 0 | col_set_str(pinfo->cinfo, COL_INFO, opname); |
217 | 0 | if(suffix) |
218 | 0 | col_append_str(pinfo->cinfo, COL_INFO, suffix); |
219 | |
|
220 | 0 | return (*opdissector)(tvb, pinfo, ros_tree, NULL); |
221 | 0 | } |
222 | 0 | } |
223 | | |
224 | 77 | return 0; |
225 | 77 | } |
226 | | |
227 | | int |
228 | | call_ros_oid_callback(const char *oid, tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, struct SESSION_DATA_STRUCTURE* session) |
229 | 77 | { |
230 | 77 | tvbuff_t *next_tvb; |
231 | 77 | int len; |
232 | | |
233 | 77 | next_tvb = tvb_new_subset_remaining(tvb, offset); |
234 | | |
235 | 77 | if(((len = ros_try_string(oid, next_tvb, pinfo, tree, session)) == 0) && |
236 | 77 | ((len = dissector_try_string_with_data(ros_oid_dissector_table, oid, next_tvb, pinfo, tree, true, session)) == 0)) { |
237 | 77 | proto_item *item; |
238 | 77 | proto_tree *next_tree; |
239 | | |
240 | 77 | next_tree = proto_tree_add_subtree_format(tree, next_tvb, 0, -1, ett_ros_unknown, &item, |
241 | 77 | "ROS: Dissector for OID:%s not implemented. Contact Wireshark developers if you want this supported", oid); |
242 | | |
243 | 77 | expert_add_info_format(pinfo, item, &ei_ros_dissector_oid_not_implemented, |
244 | 77 | "ROS: Dissector for OID %s not implemented", oid); |
245 | 77 | len = dissect_unknown_ber(pinfo, next_tvb, offset, next_tree); |
246 | 77 | } |
247 | | |
248 | 77 | offset += len; |
249 | | |
250 | 77 | return offset; |
251 | 77 | } |
252 | | |
253 | | |
254 | | static unsigned |
255 | | ros_info_hash_matched(const void *k) |
256 | 0 | { |
257 | 0 | const ros_call_response_t *key = (const ros_call_response_t *)k; |
258 | |
|
259 | 0 | return key->invokeId; |
260 | 0 | } |
261 | | |
262 | | static int |
263 | | ros_info_equal_matched(const void *k1, const void *k2) |
264 | 0 | { |
265 | 0 | const ros_call_response_t *key1 = (const ros_call_response_t *)k1; |
266 | 0 | const ros_call_response_t *key2 = (const ros_call_response_t *)k2; |
267 | |
|
268 | 0 | if( key1->req_frame && key2->req_frame && (key1->req_frame!=key2->req_frame) ){ |
269 | 0 | return 0; |
270 | 0 | } |
271 | | /* a response may span multiple frames |
272 | | if( key1->rep_frame && key2->rep_frame && (key1->rep_frame!=key2->rep_frame) ){ |
273 | | return 0; |
274 | | } |
275 | | */ |
276 | | |
277 | 0 | return key1->invokeId==key2->invokeId; |
278 | 0 | } |
279 | | |
280 | | static unsigned |
281 | | ros_info_hash_unmatched(const void *k) |
282 | 0 | { |
283 | 0 | const ros_call_response_t *key = (const ros_call_response_t *)k; |
284 | |
|
285 | 0 | return key->invokeId; |
286 | 0 | } |
287 | | |
288 | | static int |
289 | | ros_info_equal_unmatched(const void *k1, const void *k2) |
290 | 0 | { |
291 | 0 | const ros_call_response_t *key1 = (const ros_call_response_t *)k1; |
292 | 0 | const ros_call_response_t *key2 = (const ros_call_response_t *)k2; |
293 | |
|
294 | 0 | return key1->invokeId==key2->invokeId; |
295 | 0 | } |
296 | | |
297 | | static ros_call_response_t * |
298 | | ros_match_call_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned invokeId, bool isInvoke) |
299 | 0 | { |
300 | 0 | ros_call_response_t rcr, *rcrp=NULL; |
301 | 0 | ros_conv_info_t *ros_info; |
302 | 0 | conversation_t *conversation; |
303 | | |
304 | | /* first see if we have already matched this */ |
305 | 0 | conversation = find_conversation_pinfo(pinfo, 0); |
306 | 0 | if (conversation == NULL) |
307 | 0 | return NULL; |
308 | | |
309 | 0 | ros_info = (ros_conv_info_t *)conversation_get_proto_data(conversation, proto_ros); |
310 | 0 | if (ros_info == NULL) |
311 | 0 | return NULL; |
312 | | |
313 | 0 | rcr.invokeId=invokeId; |
314 | 0 | rcr.is_request = isInvoke; |
315 | |
|
316 | 0 | if(isInvoke) { |
317 | 0 | rcr.req_frame=pinfo->num; |
318 | 0 | rcr.rep_frame=0; |
319 | 0 | } else { |
320 | 0 | rcr.req_frame=0; |
321 | 0 | rcr.rep_frame=pinfo->num; |
322 | 0 | } |
323 | |
|
324 | 0 | rcrp=(ros_call_response_t *)wmem_map_lookup(ros_info->matched, &rcr); |
325 | |
|
326 | 0 | if(rcrp) { |
327 | | /* we have found a match */ |
328 | 0 | rcrp->is_request=rcr.is_request; |
329 | |
|
330 | 0 | } else { |
331 | | |
332 | | /* we haven't found a match - try and match it up */ |
333 | |
|
334 | 0 | if(isInvoke) { |
335 | | /* this is a request - add it to the unmatched list */ |
336 | | |
337 | | /* check that we don't already have one of those in the |
338 | | unmatched list and if so remove it */ |
339 | |
|
340 | 0 | rcr.invokeId=invokeId; |
341 | |
|
342 | 0 | rcrp=(ros_call_response_t *)wmem_map_lookup(ros_info->unmatched, &rcr); |
343 | |
|
344 | 0 | if(rcrp){ |
345 | 0 | wmem_map_remove(ros_info->unmatched, rcrp); |
346 | 0 | } |
347 | | |
348 | | /* if we can't reuse the old one, grab a new chunk */ |
349 | 0 | if(!rcrp){ |
350 | 0 | rcrp=wmem_new(wmem_file_scope(), ros_call_response_t); |
351 | 0 | } |
352 | 0 | rcrp->invokeId=invokeId; |
353 | 0 | rcrp->req_frame=pinfo->num; |
354 | 0 | rcrp->req_time=pinfo->abs_ts; |
355 | 0 | rcrp->rep_frame=0; |
356 | 0 | rcrp->is_request=true; |
357 | 0 | wmem_map_insert(ros_info->unmatched, rcrp, rcrp); |
358 | 0 | return NULL; |
359 | |
|
360 | 0 | } else { |
361 | | |
362 | | /* this is a result - it should be in our unmatched list */ |
363 | |
|
364 | 0 | rcr.invokeId=invokeId; |
365 | 0 | rcrp=(ros_call_response_t *)wmem_map_lookup(ros_info->unmatched, &rcr); |
366 | |
|
367 | 0 | if(rcrp){ |
368 | |
|
369 | 0 | if(!rcrp->rep_frame){ |
370 | 0 | wmem_map_remove(ros_info->unmatched, rcrp); |
371 | 0 | rcrp->rep_frame=pinfo->num; |
372 | 0 | rcrp->is_request=false; |
373 | 0 | wmem_map_insert(ros_info->matched, rcrp, rcrp); |
374 | 0 | } |
375 | 0 | } |
376 | 0 | } |
377 | 0 | } |
378 | | |
379 | 0 | if(rcrp){ /* we have found a match */ |
380 | 0 | proto_item *item = NULL; |
381 | |
|
382 | 0 | if(rcrp->is_request){ |
383 | 0 | item=proto_tree_add_uint(tree, hf_ros_response_in, tvb, 0, 0, rcrp->rep_frame); |
384 | 0 | proto_item_set_generated (item); |
385 | 0 | } else { |
386 | 0 | nstime_t ns; |
387 | 0 | item=proto_tree_add_uint(tree, hf_ros_response_to, tvb, 0, 0, rcrp->req_frame); |
388 | 0 | proto_item_set_generated (item); |
389 | 0 | nstime_delta(&ns, &pinfo->abs_ts, &rcrp->req_time); |
390 | 0 | item=proto_tree_add_time(tree, hf_ros_time, tvb, 0, 0, &ns); |
391 | 0 | proto_item_set_generated (item); |
392 | 0 | } |
393 | 0 | } |
394 | |
|
395 | 0 | return rcrp; |
396 | 0 | } |
397 | | |
398 | | |
399 | | |
400 | | static unsigned |
401 | 0 | dissect_ros_T_present(bool implicit_tag _U_, tvbuff_t *tvb _U_, unsigned offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
402 | 0 | offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index, |
403 | 0 | &invokeid); |
404 | |
|
405 | 0 | return offset; |
406 | 0 | } |
407 | | |
408 | | |
409 | | |
410 | | static unsigned |
411 | 0 | dissect_ros_NULL(bool implicit_tag _U_, tvbuff_t *tvb _U_, unsigned offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
412 | 0 | offset = dissect_ber_null(implicit_tag, actx, tree, tvb, offset, hf_index); |
413 | |
|
414 | 0 | return offset; |
415 | 0 | } |
416 | | |
417 | | |
418 | | const value_string ros_InvokeId_vals[] = { |
419 | | { 0, "present" }, |
420 | | { 1, "absent" }, |
421 | | { 0, NULL } |
422 | | }; |
423 | | |
424 | | static const ber_choice_t InvokeId_choice[] = { |
425 | | { 0, &hf_ros_present , BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_ros_T_present }, |
426 | | { 1, &hf_ros_absent , BER_CLASS_UNI, BER_UNI_TAG_NULL, BER_FLAGS_NOOWNTAG, dissect_ros_NULL }, |
427 | | { 0, NULL, 0, 0, 0, NULL } |
428 | | }; |
429 | | |
430 | | unsigned |
431 | 0 | dissect_ros_InvokeId(bool implicit_tag _U_, tvbuff_t *tvb _U_, unsigned offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
432 | 0 | offset = dissect_ber_choice(actx, tree, tvb, offset, |
433 | 0 | InvokeId_choice, hf_index, ett_ros_InvokeId, |
434 | 0 | NULL); |
435 | |
|
436 | 0 | return offset; |
437 | 0 | } |
438 | | |
439 | | |
440 | | |
441 | | static unsigned |
442 | 0 | dissect_ros_INTEGER(bool implicit_tag _U_, tvbuff_t *tvb _U_, unsigned offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
443 | 0 | offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index, |
444 | 0 | NULL); |
445 | |
|
446 | 0 | return offset; |
447 | 0 | } |
448 | | |
449 | | |
450 | | |
451 | | static unsigned |
452 | 0 | dissect_ros_OperationCode(bool implicit_tag _U_, tvbuff_t *tvb _U_, unsigned offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
453 | 0 | offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index, |
454 | 0 | &opcode); |
455 | |
|
456 | 0 | return offset; |
457 | 0 | } |
458 | | |
459 | | |
460 | | |
461 | | static unsigned |
462 | 0 | dissect_ros_T_argument(bool implicit_tag _U_, tvbuff_t *tvb _U_, unsigned offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
463 | 0 | char *oid; |
464 | 0 | proto_tree* subtree; |
465 | 0 | struct SESSION_DATA_STRUCTURE* session = (struct SESSION_DATA_STRUCTURE *)actx->private_data; |
466 | | |
467 | | /* not sure what the length should be - -1 for now */ |
468 | 0 | subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_ros_invoke_argument, NULL, "invoke argument"); |
469 | |
|
470 | 0 | ros_match_call_response(tvb, actx->pinfo, subtree, invokeid, true); |
471 | |
|
472 | 0 | if(session && session->pres_ctx_id && (oid = find_oid_by_pres_ctx_id(actx->pinfo, session->pres_ctx_id))) { |
473 | | /* this should be ROS! */ |
474 | 0 | session->ros_op = (ROS_OP_INVOKE | ROS_OP_ARGUMENT); |
475 | | /* now add the opcode */ |
476 | 0 | session->ros_op |= opcode; |
477 | 0 | offset = call_ros_oid_callback(oid, tvb, offset, actx->pinfo, top_tree, session); |
478 | 0 | } |
479 | | |
480 | |
|
481 | 0 | return offset; |
482 | 0 | } |
483 | | |
484 | | |
485 | | static const ber_sequence_t Invoke_sequence[] = { |
486 | | { &hf_ros_invokeId , BER_CLASS_ANY/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG|BER_FLAGS_NOTCHKTAG, dissect_ros_InvokeId }, |
487 | | { &hf_ros_linkedId , BER_CLASS_CON, 0, BER_FLAGS_OPTIONAL|BER_FLAGS_IMPLTAG, dissect_ros_INTEGER }, |
488 | | { &hf_ros_opcode , BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_ros_OperationCode }, |
489 | | { &hf_ros_argument , BER_CLASS_ANY, 0, BER_FLAGS_OPTIONAL|BER_FLAGS_NOOWNTAG, dissect_ros_T_argument }, |
490 | | { NULL, 0, 0, 0, NULL } |
491 | | }; |
492 | | |
493 | | static unsigned |
494 | 0 | dissect_ros_Invoke(bool implicit_tag _U_, tvbuff_t *tvb _U_, unsigned offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
495 | 0 | offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset, |
496 | 0 | Invoke_sequence, hf_index, ett_ros_Invoke); |
497 | |
|
498 | 0 | return offset; |
499 | 0 | } |
500 | | |
501 | | |
502 | | |
503 | | static unsigned |
504 | 0 | dissect_ros_OperationResult(bool implicit_tag _U_, tvbuff_t *tvb _U_, unsigned offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
505 | 0 | char *oid; |
506 | 0 | proto_tree* subtree; |
507 | 0 | struct SESSION_DATA_STRUCTURE* session = (struct SESSION_DATA_STRUCTURE *)actx->private_data; |
508 | | |
509 | | /* not sure what the length should be - -1 for now */ |
510 | 0 | subtree = proto_tree_add_subtree(tree, tvb, offset,-1, ett_ros_return_result, NULL, "return result"); |
511 | |
|
512 | 0 | ros_match_call_response(tvb, actx->pinfo, subtree, invokeid, false); |
513 | |
|
514 | 0 | if(session && session->pres_ctx_id && (oid = find_oid_by_pres_ctx_id(actx->pinfo, session->pres_ctx_id))) { |
515 | | /* this should be ROS! */ |
516 | 0 | session->ros_op = (ROS_OP_INVOKE | ROS_OP_RESULT); |
517 | | /* now add the opcode */ |
518 | 0 | session->ros_op |= opcode; |
519 | 0 | offset = call_ros_oid_callback(oid, tvb, offset, actx->pinfo, top_tree, session); |
520 | 0 | } |
521 | | |
522 | |
|
523 | 0 | return offset; |
524 | 0 | } |
525 | | |
526 | | |
527 | | static const ber_sequence_t T_result_sequence[] = { |
528 | | { &hf_ros_opcode , BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_ros_OperationCode }, |
529 | | { &hf_ros_operationResult , BER_CLASS_ANY, 0, BER_FLAGS_NOOWNTAG, dissect_ros_OperationResult }, |
530 | | { NULL, 0, 0, 0, NULL } |
531 | | }; |
532 | | |
533 | | static unsigned |
534 | 0 | dissect_ros_T_result(bool implicit_tag _U_, tvbuff_t *tvb _U_, unsigned offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
535 | 0 | offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset, |
536 | 0 | T_result_sequence, hf_index, ett_ros_T_result); |
537 | |
|
538 | 0 | return offset; |
539 | 0 | } |
540 | | |
541 | | |
542 | | static const ber_sequence_t ReturnResult_sequence[] = { |
543 | | { &hf_ros_invokeId , BER_CLASS_ANY/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG|BER_FLAGS_NOTCHKTAG, dissect_ros_InvokeId }, |
544 | | { &hf_ros_result , BER_CLASS_UNI, BER_UNI_TAG_SEQUENCE, BER_FLAGS_OPTIONAL|BER_FLAGS_NOOWNTAG, dissect_ros_T_result }, |
545 | | { NULL, 0, 0, 0, NULL } |
546 | | }; |
547 | | |
548 | | static unsigned |
549 | 0 | dissect_ros_ReturnResult(bool implicit_tag _U_, tvbuff_t *tvb _U_, unsigned offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
550 | 0 | offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset, |
551 | 0 | ReturnResult_sequence, hf_index, ett_ros_ReturnResult); |
552 | |
|
553 | 0 | return offset; |
554 | 0 | } |
555 | | |
556 | | |
557 | | |
558 | | static unsigned |
559 | 0 | dissect_ros_ErrorCode(bool implicit_tag _U_, tvbuff_t *tvb _U_, unsigned offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
560 | 0 | offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index, |
561 | 0 | &opcode); |
562 | |
|
563 | 0 | return offset; |
564 | 0 | } |
565 | | |
566 | | |
567 | | |
568 | | static unsigned |
569 | 0 | dissect_ros_T_parameter(bool implicit_tag _U_, tvbuff_t *tvb _U_, unsigned offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
570 | 0 | char *oid; |
571 | 0 | proto_tree* subtree; |
572 | 0 | struct SESSION_DATA_STRUCTURE* session = (struct SESSION_DATA_STRUCTURE *)actx->private_data; |
573 | | |
574 | | /* not sure what the length should be - -1 for now */ |
575 | 0 | subtree = proto_tree_add_subtree(tree, tvb, offset,-1, ett_ros_return_result, NULL, "return result"); |
576 | |
|
577 | 0 | ros_match_call_response(tvb, actx->pinfo, subtree, invokeid, false); |
578 | |
|
579 | 0 | if(session && session->pres_ctx_id && (oid = find_oid_by_pres_ctx_id(actx->pinfo, session->pres_ctx_id))) { |
580 | | /* this should be ROS! */ |
581 | 0 | session->ros_op = (ROS_OP_INVOKE | ROS_OP_ERROR); |
582 | | /* now add the opcode (really the error code) */ |
583 | 0 | session->ros_op |= opcode; |
584 | 0 | offset = call_ros_oid_callback(oid, tvb, offset, actx->pinfo, top_tree, session); |
585 | 0 | } |
586 | | |
587 | |
|
588 | 0 | return offset; |
589 | 0 | } |
590 | | |
591 | | |
592 | | static const ber_sequence_t ReturnError_sequence[] = { |
593 | | { &hf_ros_invokeId , BER_CLASS_ANY/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG|BER_FLAGS_NOTCHKTAG, dissect_ros_InvokeId }, |
594 | | { &hf_ros_errcode , BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_ros_ErrorCode }, |
595 | | { &hf_ros_parameter , BER_CLASS_ANY, 0, BER_FLAGS_OPTIONAL|BER_FLAGS_NOOWNTAG, dissect_ros_T_parameter }, |
596 | | { NULL, 0, 0, 0, NULL } |
597 | | }; |
598 | | |
599 | | static unsigned |
600 | 0 | dissect_ros_ReturnError(bool implicit_tag _U_, tvbuff_t *tvb _U_, unsigned offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
601 | 0 | offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset, |
602 | 0 | ReturnError_sequence, hf_index, ett_ros_ReturnError); |
603 | |
|
604 | 0 | return offset; |
605 | 0 | } |
606 | | |
607 | | |
608 | | static const value_string ros_GeneralProblem_vals[] = { |
609 | | { 0, "unrecognizedPDU" }, |
610 | | { 1, "mistypedPDU" }, |
611 | | { 2, "badlyStructuredPDU" }, |
612 | | { 0, NULL } |
613 | | }; |
614 | | |
615 | | |
616 | | static unsigned |
617 | 0 | dissect_ros_GeneralProblem(bool implicit_tag _U_, tvbuff_t *tvb _U_, unsigned offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
618 | 0 | uint32_t problem; |
619 | |
|
620 | 0 | offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index, |
621 | 0 | &problem); |
622 | | |
623 | |
|
624 | 0 | col_append_fstr(actx->pinfo->cinfo, COL_INFO, " %s", val_to_str(actx->pinfo->pool, problem, ros_GeneralProblem_vals, "GeneralProblem(%d)")); |
625 | | |
626 | |
|
627 | 0 | return offset; |
628 | 0 | } |
629 | | |
630 | | |
631 | | static const value_string ros_InvokeProblem_vals[] = { |
632 | | { 0, "duplicateInvocation" }, |
633 | | { 1, "unrecognizedOperation" }, |
634 | | { 2, "mistypedArgument" }, |
635 | | { 3, "resourceLimitation" }, |
636 | | { 4, "releaseInProgress" }, |
637 | | { 5, "unrecognizedLinkedId" }, |
638 | | { 6, "linkedResponseUnexpected" }, |
639 | | { 7, "unexpectedLinkedOperation" }, |
640 | | { 0, NULL } |
641 | | }; |
642 | | |
643 | | |
644 | | static unsigned |
645 | 0 | dissect_ros_InvokeProblem(bool implicit_tag _U_, tvbuff_t *tvb _U_, unsigned offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
646 | 0 | uint32_t problem; |
647 | |
|
648 | 0 | offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index, |
649 | 0 | &problem); |
650 | | |
651 | |
|
652 | 0 | col_append_fstr(actx->pinfo->cinfo, COL_INFO, " %s", val_to_str(actx->pinfo->pool, problem, ros_InvokeProblem_vals, "InvokeProblem(%d)")); |
653 | | |
654 | |
|
655 | 0 | return offset; |
656 | 0 | } |
657 | | |
658 | | |
659 | | static const value_string ros_ReturnResultProblem_vals[] = { |
660 | | { 0, "unrecognizedInvocation" }, |
661 | | { 1, "resultResponseUnexpected" }, |
662 | | { 2, "mistypedResult" }, |
663 | | { 0, NULL } |
664 | | }; |
665 | | |
666 | | |
667 | | static unsigned |
668 | 0 | dissect_ros_ReturnResultProblem(bool implicit_tag _U_, tvbuff_t *tvb _U_, unsigned offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
669 | 0 | uint32_t problem; |
670 | |
|
671 | 0 | offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index, |
672 | 0 | &problem); |
673 | | |
674 | |
|
675 | 0 | col_append_fstr(actx->pinfo->cinfo, COL_INFO, " %s", val_to_str(actx->pinfo->pool, problem, ros_ReturnResultProblem_vals, "ReturnResultProblem(%d)")); |
676 | | |
677 | |
|
678 | 0 | return offset; |
679 | 0 | } |
680 | | |
681 | | |
682 | | static const value_string ros_ReturnErrorProblem_vals[] = { |
683 | | { 0, "unrecognizedInvocation" }, |
684 | | { 1, "errorResponseUnexpected" }, |
685 | | { 2, "unrecognizedError" }, |
686 | | { 3, "unexpectedError" }, |
687 | | { 4, "mistypedParameter" }, |
688 | | { 0, NULL } |
689 | | }; |
690 | | |
691 | | |
692 | | static unsigned |
693 | 0 | dissect_ros_ReturnErrorProblem(bool implicit_tag _U_, tvbuff_t *tvb _U_, unsigned offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
694 | 0 | uint32_t problem; |
695 | |
|
696 | 0 | offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index, |
697 | 0 | &problem); |
698 | | |
699 | |
|
700 | 0 | col_append_fstr(actx->pinfo->cinfo, COL_INFO, " %s", val_to_str(actx->pinfo->pool, problem, ros_ReturnErrorProblem_vals, "ReturnErrorProblem(%d)")); |
701 | | |
702 | |
|
703 | 0 | return offset; |
704 | 0 | } |
705 | | |
706 | | |
707 | | static const value_string ros_T_problem_vals[] = { |
708 | | { 0, "general" }, |
709 | | { 1, "invoke" }, |
710 | | { 2, "returnResult" }, |
711 | | { 3, "returnError" }, |
712 | | { 0, NULL } |
713 | | }; |
714 | | |
715 | | static const ber_choice_t T_problem_choice[] = { |
716 | | { 0, &hf_ros_general , BER_CLASS_CON, 0, BER_FLAGS_IMPLTAG, dissect_ros_GeneralProblem }, |
717 | | { 1, &hf_ros_invokeProblem , BER_CLASS_CON, 1, BER_FLAGS_IMPLTAG, dissect_ros_InvokeProblem }, |
718 | | { 2, &hf_ros_rejectResult , BER_CLASS_CON, 2, BER_FLAGS_IMPLTAG, dissect_ros_ReturnResultProblem }, |
719 | | { 3, &hf_ros_rejectError , BER_CLASS_CON, 3, BER_FLAGS_IMPLTAG, dissect_ros_ReturnErrorProblem }, |
720 | | { 0, NULL, 0, 0, 0, NULL } |
721 | | }; |
722 | | |
723 | | static unsigned |
724 | 0 | dissect_ros_T_problem(bool implicit_tag _U_, tvbuff_t *tvb _U_, unsigned offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
725 | 0 | offset = dissect_ber_choice(actx, tree, tvb, offset, |
726 | 0 | T_problem_choice, hf_index, ett_ros_T_problem, |
727 | 0 | NULL); |
728 | |
|
729 | 0 | return offset; |
730 | 0 | } |
731 | | |
732 | | |
733 | | static const ber_sequence_t Reject_sequence[] = { |
734 | | { &hf_ros_invokeId , BER_CLASS_ANY/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG|BER_FLAGS_NOTCHKTAG, dissect_ros_InvokeId }, |
735 | | { &hf_ros_problem , BER_CLASS_ANY/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG|BER_FLAGS_NOTCHKTAG, dissect_ros_T_problem }, |
736 | | { NULL, 0, 0, 0, NULL } |
737 | | }; |
738 | | |
739 | | static unsigned |
740 | 0 | dissect_ros_Reject(bool implicit_tag _U_, tvbuff_t *tvb _U_, unsigned offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
741 | 0 | offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset, |
742 | 0 | Reject_sequence, hf_index, ett_ros_Reject); |
743 | |
|
744 | 0 | return offset; |
745 | 0 | } |
746 | | |
747 | | |
748 | | |
749 | | static unsigned |
750 | 0 | dissect_ros_T_reject(bool implicit_tag _U_, tvbuff_t *tvb _U_, unsigned offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
751 | 0 | col_set_str(actx->pinfo->cinfo, COL_INFO, "Reject"); |
752 | 0 | offset = dissect_ros_Reject(implicit_tag, tvb, offset, actx, tree, hf_index); |
753 | | |
754 | | |
755 | |
|
756 | 0 | return offset; |
757 | 0 | } |
758 | | |
759 | | |
760 | | |
761 | | static unsigned |
762 | 0 | dissect_ros_T_bind_invoke(bool implicit_tag _U_, tvbuff_t *tvb _U_, unsigned offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
763 | 0 | char *oid; |
764 | 0 | struct SESSION_DATA_STRUCTURE* session = (struct SESSION_DATA_STRUCTURE *)actx->private_data; |
765 | | |
766 | | /* not sure what the length should be - -1 for now */ |
767 | 0 | proto_tree_add_subtree(tree, tvb, offset,-1, ett_ros_bind_result, NULL, "bind-invoke"); |
768 | |
|
769 | 0 | if(session && session->pres_ctx_id && (oid = find_oid_by_pres_ctx_id(actx->pinfo, session->pres_ctx_id))) { |
770 | | /* this should be ROS! */ |
771 | 0 | session->ros_op = (ROS_OP_BIND | ROS_OP_ARGUMENT); |
772 | 0 | offset = call_ros_oid_callback(oid, tvb, offset, actx->pinfo, top_tree, session); |
773 | 0 | } |
774 | | |
775 | |
|
776 | 0 | return offset; |
777 | 0 | } |
778 | | |
779 | | |
780 | | |
781 | | static unsigned |
782 | 0 | dissect_ros_T_bind_result(bool implicit_tag _U_, tvbuff_t *tvb _U_, unsigned offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
783 | 0 | char *oid; |
784 | 0 | struct SESSION_DATA_STRUCTURE* session = (struct SESSION_DATA_STRUCTURE *)actx->private_data; |
785 | | |
786 | | /* not sure what the length should be - -1 for now */ |
787 | 0 | proto_tree_add_subtree(tree, tvb, offset,-1, ett_ros_bind_result, NULL, "bind-result"); |
788 | |
|
789 | 0 | if(session && session->pres_ctx_id && (oid = find_oid_by_pres_ctx_id(actx->pinfo, session->pres_ctx_id))) { |
790 | | /* this should be ROS! */ |
791 | 0 | session->ros_op = (ROS_OP_BIND | ROS_OP_RESULT); |
792 | 0 | offset = call_ros_oid_callback(oid, tvb, offset, actx->pinfo, top_tree, session); |
793 | 0 | } |
794 | | |
795 | |
|
796 | 0 | return offset; |
797 | 0 | } |
798 | | |
799 | | |
800 | | |
801 | | static unsigned |
802 | 0 | dissect_ros_T_bind_error(bool implicit_tag _U_, tvbuff_t *tvb _U_, unsigned offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
803 | 0 | char *oid; |
804 | 0 | struct SESSION_DATA_STRUCTURE* session = (struct SESSION_DATA_STRUCTURE *)actx->private_data; |
805 | | |
806 | | /* not sure what the length should be - -1 for now */ |
807 | 0 | proto_tree_add_subtree(tree, tvb, offset,-1, ett_ros_bind_error, NULL, "bind-error"); |
808 | |
|
809 | 0 | if(session && session->pres_ctx_id && (oid = find_oid_by_pres_ctx_id(actx->pinfo, session->pres_ctx_id))) { |
810 | | /* this should be ROS! */ |
811 | 0 | session->ros_op = (ROS_OP_BIND | ROS_OP_ERROR); |
812 | 0 | offset = call_ros_oid_callback(oid, tvb, offset, actx->pinfo, top_tree, session); |
813 | 0 | } |
814 | | |
815 | | |
816 | |
|
817 | 0 | return offset; |
818 | 0 | } |
819 | | |
820 | | |
821 | | |
822 | | static unsigned |
823 | 0 | dissect_ros_T_unbind_invoke(bool implicit_tag _U_, tvbuff_t *tvb _U_, unsigned offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
824 | 0 | char *oid; |
825 | 0 | struct SESSION_DATA_STRUCTURE* session = (struct SESSION_DATA_STRUCTURE *)actx->private_data; |
826 | | |
827 | | /* not sure what the length should be - -1 for now */ |
828 | 0 | proto_tree_add_subtree(tree, tvb, offset,-1, ett_ros_unbind_invoke, NULL, "unbind-invoke"); |
829 | |
|
830 | 0 | if(session && session->pres_ctx_id && (oid = find_oid_by_pres_ctx_id(actx->pinfo, session->pres_ctx_id))) { |
831 | | /* this should be ROS! */ |
832 | 0 | session->ros_op = (ROS_OP_UNBIND | ROS_OP_ARGUMENT); |
833 | 0 | offset = call_ros_oid_callback(oid, tvb, offset, actx->pinfo, top_tree, session); |
834 | 0 | } |
835 | | |
836 | | |
837 | |
|
838 | 0 | return offset; |
839 | 0 | } |
840 | | |
841 | | |
842 | | |
843 | | static unsigned |
844 | 0 | dissect_ros_T_unbind_result(bool implicit_tag _U_, tvbuff_t *tvb _U_, unsigned offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
845 | 0 | char *oid; |
846 | 0 | struct SESSION_DATA_STRUCTURE* session = (struct SESSION_DATA_STRUCTURE *)actx->private_data; |
847 | | |
848 | | /* not sure what the length should be - -1 for now */ |
849 | 0 | proto_tree_add_subtree(tree, tvb, offset,-1, ett_ros_unbind_result, NULL, "unbind-result"); |
850 | |
|
851 | 0 | if(session && session->pres_ctx_id && (oid = find_oid_by_pres_ctx_id(actx->pinfo, session->pres_ctx_id))) { |
852 | | /* this should be ROS! */ |
853 | 0 | session->ros_op = (ROS_OP_UNBIND | ROS_OP_RESULT); |
854 | 0 | offset = call_ros_oid_callback(oid, tvb, offset, actx->pinfo, top_tree, session); |
855 | 0 | } |
856 | | |
857 | |
|
858 | 0 | return offset; |
859 | 0 | } |
860 | | |
861 | | |
862 | | |
863 | | static unsigned |
864 | 0 | dissect_ros_T_unbind_error(bool implicit_tag _U_, tvbuff_t *tvb _U_, unsigned offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
865 | 0 | char *oid; |
866 | 0 | struct SESSION_DATA_STRUCTURE* session = (struct SESSION_DATA_STRUCTURE *)actx->private_data; |
867 | | |
868 | | /* not sure what the length should be - -1 for now */ |
869 | 0 | proto_tree_add_subtree(tree, tvb, offset,-1, ett_ros_unbind_error, NULL, "unbind-error"); |
870 | |
|
871 | 0 | if(session && session->pres_ctx_id && (oid = find_oid_by_pres_ctx_id(actx->pinfo, session->pres_ctx_id))) { |
872 | | /* this should be ROS! */ |
873 | 0 | session->ros_op = (ROS_OP_UNBIND | ROS_OP_ERROR); |
874 | 0 | offset = call_ros_oid_callback(oid, tvb, offset, actx->pinfo, top_tree, session); |
875 | 0 | } |
876 | | |
877 | |
|
878 | 0 | return offset; |
879 | 0 | } |
880 | | |
881 | | |
882 | | const value_string ros_ROS_vals[] = { |
883 | | { 1, "invoke" }, |
884 | | { 2, "returnResult" }, |
885 | | { 3, "returnError" }, |
886 | | { 4, "reject" }, |
887 | | { 16, "bind-invoke" }, |
888 | | { 17, "bind-result" }, |
889 | | { 18, "bind-error" }, |
890 | | { 19, "unbind-invoke" }, |
891 | | { 20, "unbind-result" }, |
892 | | { 21, "unbind-error" }, |
893 | | { 0, NULL } |
894 | | }; |
895 | | |
896 | | static const ber_choice_t ROS_choice[] = { |
897 | | { 1, &hf_ros_invoke , BER_CLASS_CON, 1, BER_FLAGS_IMPLTAG, dissect_ros_Invoke }, |
898 | | { 2, &hf_ros_returnResult , BER_CLASS_CON, 2, BER_FLAGS_IMPLTAG, dissect_ros_ReturnResult }, |
899 | | { 3, &hf_ros_returnError , BER_CLASS_CON, 3, BER_FLAGS_IMPLTAG, dissect_ros_ReturnError }, |
900 | | { 4, &hf_ros_reject , BER_CLASS_CON, 4, BER_FLAGS_IMPLTAG, dissect_ros_T_reject }, |
901 | | { 16, &hf_ros_bind_invoke , BER_CLASS_CON, 16, BER_FLAGS_IMPLTAG, dissect_ros_T_bind_invoke }, |
902 | | { 17, &hf_ros_bind_result , BER_CLASS_CON, 17, BER_FLAGS_IMPLTAG, dissect_ros_T_bind_result }, |
903 | | { 18, &hf_ros_bind_error , BER_CLASS_CON, 18, BER_FLAGS_IMPLTAG, dissect_ros_T_bind_error }, |
904 | | { 19, &hf_ros_unbind_invoke , BER_CLASS_CON, 19, BER_FLAGS_IMPLTAG, dissect_ros_T_unbind_invoke }, |
905 | | { 20, &hf_ros_unbind_result , BER_CLASS_CON, 20, BER_FLAGS_IMPLTAG, dissect_ros_T_unbind_result }, |
906 | | { 21, &hf_ros_unbind_error , BER_CLASS_CON, 21, BER_FLAGS_IMPLTAG, dissect_ros_T_unbind_error }, |
907 | | { 0, NULL, 0, 0, 0, NULL } |
908 | | }; |
909 | | |
910 | | unsigned |
911 | 0 | dissect_ros_ROS(bool implicit_tag _U_, tvbuff_t *tvb _U_, unsigned offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
912 | 0 | offset = dissect_ber_choice(actx, tree, tvb, offset, |
913 | 0 | ROS_choice, hf_index, ett_ros_ROS, |
914 | 0 | NULL); |
915 | |
|
916 | 0 | return offset; |
917 | 0 | } |
918 | | |
919 | | |
920 | | |
921 | | static unsigned |
922 | 0 | dissect_ros_OBJECT_IDENTIFIER(bool implicit_tag _U_, tvbuff_t *tvb _U_, unsigned offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
923 | 0 | offset = dissect_ber_object_identifier(implicit_tag, actx, tree, tvb, offset, hf_index, NULL); |
924 | |
|
925 | 0 | return offset; |
926 | 0 | } |
927 | | |
928 | | |
929 | | const value_string ros_Code_vals[] = { |
930 | | { 0, "local" }, |
931 | | { 1, "global" }, |
932 | | { 0, NULL } |
933 | | }; |
934 | | |
935 | | static const ber_choice_t Code_choice[] = { |
936 | | { 0, &hf_ros_local , BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_ros_INTEGER }, |
937 | | { 1, &hf_ros_global , BER_CLASS_UNI, BER_UNI_TAG_OID, BER_FLAGS_NOOWNTAG, dissect_ros_OBJECT_IDENTIFIER }, |
938 | | { 0, NULL, 0, 0, 0, NULL } |
939 | | }; |
940 | | |
941 | | unsigned |
942 | 0 | dissect_ros_Code(bool implicit_tag _U_, tvbuff_t *tvb _U_, unsigned offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
943 | 0 | offset = dissect_ber_choice(actx, tree, tvb, offset, |
944 | 0 | Code_choice, hf_index, ett_ros_Code, |
945 | 0 | NULL); |
946 | |
|
947 | 0 | return offset; |
948 | 0 | } |
949 | | |
950 | | |
951 | | /* |
952 | | * Dissect ROS PDUs inside a PPDU. |
953 | | */ |
954 | | static int |
955 | | dissect_ros(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data) |
956 | 0 | { |
957 | 0 | unsigned offset = 0; |
958 | 0 | unsigned old_offset; |
959 | 0 | proto_item *item; |
960 | 0 | proto_tree *tree; |
961 | 0 | proto_tree *next_tree=NULL; |
962 | 0 | conversation_t *conversation; |
963 | 0 | ros_conv_info_t *ros_info = NULL; |
964 | 0 | asn1_ctx_t asn1_ctx; |
965 | 0 | asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, true, pinfo); |
966 | | |
967 | | /* do we have application context from the acse dissector? */ |
968 | 0 | if (data == NULL) |
969 | 0 | return 0; |
970 | 0 | asn1_ctx.private_data = data; |
971 | | |
972 | | /* save parent_tree so subdissectors can create new top nodes */ |
973 | 0 | top_tree=parent_tree; |
974 | |
|
975 | 0 | conversation = find_or_create_conversation(pinfo); |
976 | | |
977 | | /* |
978 | | * Do we already have our info |
979 | | */ |
980 | 0 | ros_info = (ros_conv_info_t *)conversation_get_proto_data(conversation, proto_ros); |
981 | 0 | if (ros_info == NULL) { |
982 | | |
983 | | /* No. Attach that information to the conversation. */ |
984 | |
|
985 | 0 | ros_info = (ros_conv_info_t *)wmem_new0(wmem_file_scope(), ros_conv_info_t); |
986 | 0 | ros_info->matched=wmem_map_new(wmem_file_scope(), ros_info_hash_matched, ros_info_equal_matched); |
987 | 0 | ros_info->unmatched=wmem_map_new(wmem_file_scope(), ros_info_hash_unmatched, ros_info_equal_unmatched); |
988 | |
|
989 | 0 | conversation_add_proto_data(conversation, proto_ros, ros_info); |
990 | 0 | } |
991 | |
|
992 | 0 | item = proto_tree_add_item(parent_tree, proto_ros, tvb, 0, -1, ENC_NA); |
993 | 0 | tree = proto_item_add_subtree(item, ett_ros); |
994 | |
|
995 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "ROS"); |
996 | 0 | col_clear(pinfo->cinfo, COL_INFO); |
997 | |
|
998 | 0 | while (tvb_reported_length_remaining(tvb, offset) > 0){ |
999 | 0 | old_offset=offset; |
1000 | 0 | offset=dissect_ros_ROS(false, tvb, offset, &asn1_ctx , tree, -1); |
1001 | 0 | if(offset == old_offset){ |
1002 | 0 | next_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_ros_unknown, &item, "Unknown ROS PDU"); |
1003 | |
|
1004 | 0 | expert_add_info(pinfo, item, &ei_ros_unknown_ros_pdu); |
1005 | 0 | dissect_unknown_ber(pinfo, tvb, offset, next_tree); |
1006 | 0 | break; |
1007 | 0 | } |
1008 | 0 | } |
1009 | |
|
1010 | 0 | return tvb_captured_length(tvb); |
1011 | 0 | } |
1012 | | |
1013 | | /*--- proto_register_ros -------------------------------------------*/ |
1014 | 15 | void proto_register_ros(void) { |
1015 | | |
1016 | | /* List of fields */ |
1017 | 15 | static hf_register_info hf[] = |
1018 | 15 | { |
1019 | 15 | { &hf_ros_response_in, |
1020 | 15 | { "Response In", "ros.response_in", |
1021 | 15 | FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE), 0x0, |
1022 | 15 | "The response to this remote operation invocation is in this frame", HFILL }}, |
1023 | 15 | { &hf_ros_response_to, |
1024 | 15 | { "Response To", "ros.response_to", |
1025 | 15 | FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST), 0x0, |
1026 | 15 | "This is a response to the remote operation invocation in this frame", HFILL }}, |
1027 | 15 | { &hf_ros_time, |
1028 | 15 | { "Time", "ros.time", |
1029 | 15 | FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0, |
1030 | 15 | "The time between the Invoke and the Response", HFILL }}, |
1031 | | |
1032 | 15 | { &hf_ros_invoke, |
1033 | 15 | { "invoke", "ros.invoke_element", |
1034 | 15 | FT_NONE, BASE_NONE, NULL, 0, |
1035 | 15 | NULL, HFILL }}, |
1036 | 15 | { &hf_ros_returnResult, |
1037 | 15 | { "returnResult", "ros.returnResult_element", |
1038 | 15 | FT_NONE, BASE_NONE, NULL, 0, |
1039 | 15 | NULL, HFILL }}, |
1040 | 15 | { &hf_ros_returnError, |
1041 | 15 | { "returnError", "ros.returnError_element", |
1042 | 15 | FT_NONE, BASE_NONE, NULL, 0, |
1043 | 15 | NULL, HFILL }}, |
1044 | 15 | { &hf_ros_reject, |
1045 | 15 | { "reject", "ros.reject_element", |
1046 | 15 | FT_NONE, BASE_NONE, NULL, 0, |
1047 | 15 | NULL, HFILL }}, |
1048 | 15 | { &hf_ros_bind_invoke, |
1049 | 15 | { "bind-invoke", "ros.bind_invoke_element", |
1050 | 15 | FT_NONE, BASE_NONE, NULL, 0, |
1051 | 15 | NULL, HFILL }}, |
1052 | 15 | { &hf_ros_bind_result, |
1053 | 15 | { "bind-result", "ros.bind_result_element", |
1054 | 15 | FT_NONE, BASE_NONE, NULL, 0, |
1055 | 15 | NULL, HFILL }}, |
1056 | 15 | { &hf_ros_bind_error, |
1057 | 15 | { "bind-error", "ros.bind_error_element", |
1058 | 15 | FT_NONE, BASE_NONE, NULL, 0, |
1059 | 15 | NULL, HFILL }}, |
1060 | 15 | { &hf_ros_unbind_invoke, |
1061 | 15 | { "unbind-invoke", "ros.unbind_invoke_element", |
1062 | 15 | FT_NONE, BASE_NONE, NULL, 0, |
1063 | 15 | NULL, HFILL }}, |
1064 | 15 | { &hf_ros_unbind_result, |
1065 | 15 | { "unbind-result", "ros.unbind_result_element", |
1066 | 15 | FT_NONE, BASE_NONE, NULL, 0, |
1067 | 15 | NULL, HFILL }}, |
1068 | 15 | { &hf_ros_unbind_error, |
1069 | 15 | { "unbind-error", "ros.unbind_error_element", |
1070 | 15 | FT_NONE, BASE_NONE, NULL, 0, |
1071 | 15 | NULL, HFILL }}, |
1072 | 15 | { &hf_ros_invokeId, |
1073 | 15 | { "invokeId", "ros.invokeId", |
1074 | 15 | FT_UINT32, BASE_DEC, VALS(ros_InvokeId_vals), 0, |
1075 | 15 | NULL, HFILL }}, |
1076 | 15 | { &hf_ros_linkedId, |
1077 | 15 | { "linkedId", "ros.linkedId", |
1078 | 15 | FT_INT32, BASE_DEC, NULL, 0, |
1079 | 15 | "INTEGER", HFILL }}, |
1080 | 15 | { &hf_ros_opcode, |
1081 | 15 | { "opcode", "ros.opcode", |
1082 | 15 | FT_INT32, BASE_DEC, NULL, 0, |
1083 | 15 | "OperationCode", HFILL }}, |
1084 | 15 | { &hf_ros_argument, |
1085 | 15 | { "argument", "ros.argument_element", |
1086 | 15 | FT_NONE, BASE_NONE, NULL, 0, |
1087 | 15 | NULL, HFILL }}, |
1088 | 15 | { &hf_ros_result, |
1089 | 15 | { "result", "ros.result_element", |
1090 | 15 | FT_NONE, BASE_NONE, NULL, 0, |
1091 | 15 | NULL, HFILL }}, |
1092 | 15 | { &hf_ros_operationResult, |
1093 | 15 | { "result", "ros.operationResult_element", |
1094 | 15 | FT_NONE, BASE_NONE, NULL, 0, |
1095 | 15 | "OperationResult", HFILL }}, |
1096 | 15 | { &hf_ros_errcode, |
1097 | 15 | { "errcode", "ros.errcode", |
1098 | 15 | FT_INT32, BASE_DEC, NULL, 0, |
1099 | 15 | "ErrorCode", HFILL }}, |
1100 | 15 | { &hf_ros_parameter, |
1101 | 15 | { "parameter", "ros.parameter_element", |
1102 | 15 | FT_NONE, BASE_NONE, NULL, 0, |
1103 | 15 | NULL, HFILL }}, |
1104 | 15 | { &hf_ros_problem, |
1105 | 15 | { "problem", "ros.problem", |
1106 | 15 | FT_UINT32, BASE_DEC, VALS(ros_T_problem_vals), 0, |
1107 | 15 | NULL, HFILL }}, |
1108 | 15 | { &hf_ros_general, |
1109 | 15 | { "general", "ros.general", |
1110 | 15 | FT_INT32, BASE_DEC, VALS(ros_GeneralProblem_vals), 0, |
1111 | 15 | "GeneralProblem", HFILL }}, |
1112 | 15 | { &hf_ros_invokeProblem, |
1113 | 15 | { "invoke", "ros.invokeProblem", |
1114 | 15 | FT_INT32, BASE_DEC, VALS(ros_InvokeProblem_vals), 0, |
1115 | 15 | "InvokeProblem", HFILL }}, |
1116 | 15 | { &hf_ros_rejectResult, |
1117 | 15 | { "returnResult", "ros.rejectResult", |
1118 | 15 | FT_INT32, BASE_DEC, VALS(ros_ReturnResultProblem_vals), 0, |
1119 | 15 | "ReturnResultProblem", HFILL }}, |
1120 | 15 | { &hf_ros_rejectError, |
1121 | 15 | { "returnError", "ros.rejectError", |
1122 | 15 | FT_INT32, BASE_DEC, VALS(ros_ReturnErrorProblem_vals), 0, |
1123 | 15 | "ReturnErrorProblem", HFILL }}, |
1124 | 15 | { &hf_ros_present, |
1125 | 15 | { "present", "ros.present", |
1126 | 15 | FT_INT32, BASE_DEC, NULL, 0, |
1127 | 15 | NULL, HFILL }}, |
1128 | 15 | { &hf_ros_absent, |
1129 | 15 | { "absent", "ros.absent_element", |
1130 | 15 | FT_NONE, BASE_NONE, NULL, 0, |
1131 | 15 | NULL, HFILL }}, |
1132 | 15 | { &hf_ros_local, |
1133 | 15 | { "local", "ros.local", |
1134 | 15 | FT_INT32, BASE_DEC, NULL, 0, |
1135 | 15 | "INTEGER", HFILL }}, |
1136 | 15 | { &hf_ros_global, |
1137 | 15 | { "global", "ros.global", |
1138 | 15 | FT_OID, BASE_NONE, NULL, 0, |
1139 | 15 | "OBJECT_IDENTIFIER", HFILL }}, |
1140 | 15 | }; |
1141 | | |
1142 | | /* List of subtrees */ |
1143 | 15 | static int *ett[] = { |
1144 | 15 | &ett_ros, |
1145 | 15 | &ett_ros_unknown, |
1146 | 15 | &ett_ros_invoke_argument, |
1147 | 15 | &ett_ros_return_result, |
1148 | 15 | &ett_ros_bind_invoke, |
1149 | 15 | &ett_ros_bind_result, |
1150 | 15 | &ett_ros_bind_error, |
1151 | 15 | &ett_ros_unbind_invoke, |
1152 | 15 | &ett_ros_unbind_result, |
1153 | 15 | &ett_ros_unbind_error, |
1154 | | |
1155 | 15 | &ett_ros_ROS, |
1156 | 15 | &ett_ros_Invoke, |
1157 | 15 | &ett_ros_ReturnResult, |
1158 | 15 | &ett_ros_T_result, |
1159 | 15 | &ett_ros_ReturnError, |
1160 | 15 | &ett_ros_Reject, |
1161 | 15 | &ett_ros_T_problem, |
1162 | 15 | &ett_ros_InvokeId, |
1163 | 15 | &ett_ros_Code, |
1164 | 15 | }; |
1165 | | |
1166 | 15 | static ei_register_info ei[] = { |
1167 | 15 | { &ei_ros_dissector_oid_not_implemented, { "ros.dissector_oid_not_implemented", PI_UNDECODED, PI_WARN, "ROS: Dissector for OID not implemented", EXPFILL }}, |
1168 | 15 | { &ei_ros_unknown_ros_pdu, { "ros.unknown_ros_pdu", PI_UNDECODED, PI_WARN, "Unknown ROS PDU", EXPFILL }}, |
1169 | 15 | }; |
1170 | | |
1171 | 15 | expert_module_t* expert_ros; |
1172 | | |
1173 | | /* Register protocol */ |
1174 | 15 | proto_ros = proto_register_protocol("X.880 OSI Remote Operations Service", "ROS", "ros"); |
1175 | 15 | ros_handle = register_dissector("ros", dissect_ros, proto_ros); |
1176 | | /* Register fields and subtrees */ |
1177 | 15 | proto_register_field_array(proto_ros, hf, array_length(hf)); |
1178 | 15 | proto_register_subtree_array(ett, array_length(ett)); |
1179 | 15 | expert_ros = expert_register_protocol(proto_ros); |
1180 | 15 | expert_register_field_array(expert_ros, ei, array_length(ei)); |
1181 | | |
1182 | 15 | ros_oid_dissector_table = register_dissector_table("ros.oid", "ROS OID Dissectors", proto_ros, FT_STRING, STRING_CASE_SENSITIVE); |
1183 | 15 | protocol_table = wmem_map_new(wmem_epan_scope(), wmem_str_hash, g_str_equal); |
1184 | 15 | } |
1185 | | |
1186 | | |
1187 | | /*--- proto_reg_handoff_ros --- */ |
1188 | 15 | void proto_reg_handoff_ros(void) { |
1189 | | |
1190 | | |
1191 | 15 | } |