/src/wireshark/epan/dissectors/packet-iuup.c
Line | Count | Source |
1 | | /* packet-iuup.c |
2 | | * IuUP Protocol 3GPP TS 25.415 V6.2.0 (2005-03) |
3 | | * |
4 | | * (c) 2005 Luis E. Garcia Ontanon <luis@ontanon.org> |
5 | | * |
6 | | * Wireshark - Network traffic analyzer |
7 | | * By Gerald Combs <gerald@wireshark.org> |
8 | | * Copyright 1998 Gerald Combs |
9 | | * |
10 | | * SPDX-License-Identifier: GPL-2.0-or-later |
11 | | */ |
12 | | |
13 | | |
14 | | /* |
15 | | Patch by Polystar (Peter Vestman, Petter Edblom): |
16 | | Corrected rfci handling in rate control messages |
17 | | Added crc6 and crc10 checks for header and payload |
18 | | */ |
19 | | |
20 | | #include "config.h" |
21 | | |
22 | | #include <epan/packet.h> |
23 | | #include <epan/prefs.h> |
24 | | #include <epan/expert.h> |
25 | | #include <epan/conversation.h> |
26 | | #include <epan/crc10-tvb.h> |
27 | | #include <epan/crc6-tvb.h> |
28 | | #include <wsutil/crc10.h> |
29 | | #include <wsutil/crc6.h> |
30 | | |
31 | | #include "packet-rtp.h" |
32 | | #include "packet-iuup.h" |
33 | | |
34 | | void proto_reg_handoff_iuup(void); |
35 | | void proto_register_iuup(void); |
36 | | |
37 | | static int proto_iuup; |
38 | | |
39 | | static int hf_iuup_direction; |
40 | | static int hf_iuup_circuit_id; |
41 | | |
42 | | static int hf_iuup_pdu_type; |
43 | | static int hf_iuup_frame_number; |
44 | | static int hf_iuup_fqc; |
45 | | static int hf_iuup_rfci; |
46 | | static int hf_iuup_hdr_crc; |
47 | | static int hf_iuup_payload_crc; |
48 | | |
49 | | static int hf_iuup_ack_nack; |
50 | | static int hf_iuup_frame_number_t14; |
51 | | static int hf_iuup_mode_version; |
52 | | static int hf_iuup_procedure_indicator; |
53 | | static int hf_iuup_error_cause_val; |
54 | | |
55 | | static int hf_iuup_init_ti; |
56 | | static int hf_iuup_init_subflows_per_rfci; |
57 | | static int hf_iuup_init_chain_ind; |
58 | | |
59 | | static int hf_iuup_error_distance; |
60 | | static int hf_iuup_errorevt_cause_val; |
61 | | |
62 | | static int hf_iuup_time_align; |
63 | | static int hf_iuup_spare_bytes; |
64 | | static int hf_iuup_spare_03; |
65 | | /* static int hf_iuup_spare_0f; */ |
66 | | /* static int hf_iuup_spare_c0; */ |
67 | | static int hf_iuup_spare_e0; |
68 | | static int hf_iuup_spare_ff; |
69 | | |
70 | | static int hf_iuup_delay; |
71 | | static int hf_iuup_advance; |
72 | | static int hf_iuup_delta; |
73 | | |
74 | | static int hf_iuup_mode_versions; |
75 | | static int hf_iuup_mode_versions_a[16]; |
76 | | |
77 | | |
78 | | static int hf_iuup_data_pdu_type; |
79 | | |
80 | | static int hf_iuup_num_rfci_ind; |
81 | | |
82 | | static int hf_iuup_payload; |
83 | | |
84 | | static int hf_iuup_init_rfci_ind; |
85 | | static int hf_iuup_init_rfci[64]; |
86 | | |
87 | | static int hf_iuup_init_rfci_flow_len[64][8]; |
88 | | static int hf_iuup_init_rfci_li[64]; |
89 | | static int hf_iuup_init_rfci_lri[64]; |
90 | | static int hf_iuup_init_ipti[64]; |
91 | | static int hf_iuup_rfci_subflow[64][8]; |
92 | | static int hf_iuup_rfci_ratectl[64]; |
93 | | |
94 | | |
95 | | static int ett_iuup; |
96 | | static int ett_rfci; |
97 | | static int ett_ipti; |
98 | | static int ett_support; |
99 | | static int ett_time; |
100 | | static int ett_rfciinds; |
101 | | static int ett_payload; |
102 | | static int ett_payload_subflows; |
103 | | |
104 | | static expert_field ei_iuup_hdr_crc_bad; |
105 | | static expert_field ei_iuup_payload_crc_bad; |
106 | | static expert_field ei_iuup_payload_undecoded; |
107 | | static expert_field ei_iuup_error_response; |
108 | | static expert_field ei_iuup_ack_nack; |
109 | | static expert_field ei_iuup_time_align; |
110 | | static expert_field ei_iuup_procedure_indicator; |
111 | | static expert_field ei_iuup_pdu_type; |
112 | | static expert_field ei_iuup_too_many_rfcis; |
113 | | |
114 | | static wmem_map_t* circuits; |
115 | | |
116 | | static dissector_handle_t iuup_handle; |
117 | | |
118 | | static bool dissect_fields; |
119 | | static bool two_byte_pseudoheader; |
120 | | |
121 | | static const value_string iuup_pdu_types[] = { |
122 | | {PDUTYPE_DATA_WITH_CRC,"Data with CRC"}, |
123 | | {PDUTYPE_DATA_NO_CRC,"Data without CRC"}, |
124 | | {PDUTYPE_DATA_CONTROL_PROC,"Control Procedure"}, |
125 | | {0,NULL} |
126 | | }; |
127 | | |
128 | | static const value_string iuup_colinfo_pdu_types[] = { |
129 | | {PDUTYPE_DATA_WITH_CRC,"Data (CRC)"}, |
130 | | {PDUTYPE_DATA_NO_CRC,"Data (no CRC)"}, |
131 | | {PDUTYPE_DATA_CONTROL_PROC,""}, |
132 | | {0,NULL} |
133 | | }; |
134 | | |
135 | 0 | #define ACKNACK_ACK 0x4 |
136 | 0 | #define ACKNACK_NACK 0x8 |
137 | 0 | #define ACKNACK_RESERVED 0xc |
138 | 0 | #define ACKNACK_PROC 0x0 |
139 | | |
140 | | static const value_string iuup_acknack_vals[] = { |
141 | | {ACKNACK_PROC >> 2,"Procedure"}, |
142 | | {ACKNACK_ACK >> 2,"ACK"}, |
143 | | {ACKNACK_NACK >> 2,"NACK"}, |
144 | | {ACKNACK_RESERVED >> 2,"Reserved"}, |
145 | | {0,NULL} |
146 | | }; |
147 | | |
148 | | static const value_string iuup_colinfo_acknack_vals[] = { |
149 | | {ACKNACK_PROC,""}, |
150 | | {ACKNACK_ACK,"ACK "}, |
151 | | {ACKNACK_NACK,"NACK "}, |
152 | | {ACKNACK_RESERVED,"Reserved "}, |
153 | | {0,NULL} |
154 | | }; |
155 | | |
156 | 0 | #define PROC_INIT 0 |
157 | 0 | #define PROC_RATE 1 |
158 | 0 | #define PROC_TIME 2 |
159 | 0 | #define PROC_ERROR 3 |
160 | | |
161 | | static const value_string iuup_procedures[] = { |
162 | | {PROC_INIT,"Initialization"}, |
163 | | {PROC_RATE,"Rate Control"}, |
164 | | {PROC_TIME,"Time Alignment"}, |
165 | | {PROC_ERROR,"Error Event"}, |
166 | | {4,"Reserved(4)"}, |
167 | | {5,"Reserved(5)"}, |
168 | | {6,"Reserved(6)"}, |
169 | | {7,"Reserved(7)"}, |
170 | | {8,"Reserved(8)"}, |
171 | | {9,"Reserved(9)"}, |
172 | | {10,"Reserved(10)"}, |
173 | | {11,"Reserved(11)"}, |
174 | | {12,"Reserved(12)"}, |
175 | | {13,"Reserved(13)"}, |
176 | | {14,"Reserved(14)"}, |
177 | | {15,"Reserved(15)"}, |
178 | | {0,NULL} |
179 | | }; |
180 | | |
181 | | static const value_string iuup_colinfo_procedures[] = { |
182 | | {PROC_INIT,"Initialization "}, |
183 | | {PROC_RATE,"Rate Control "}, |
184 | | {PROC_TIME,"Time Alignment "}, |
185 | | {PROC_ERROR,"Error Event "}, |
186 | | {0,NULL} |
187 | | }; |
188 | | |
189 | | |
190 | | static const value_string iuup_error_distances[] = { |
191 | | {0, "Reporting local error"}, |
192 | | {1, "First forwarding of error event report"}, |
193 | | {2, "Second forwarding of error event report"}, |
194 | | {3, "Reserved"}, |
195 | | {0,NULL} |
196 | | }; |
197 | | |
198 | | static const value_string iuup_error_causes[] = { |
199 | | {0, "CRC error of frame header"}, |
200 | | {1, "CRC error of frame payload"}, |
201 | | {2, "Unexpected frame number"}, |
202 | | {3, "Frame loss"}, |
203 | | {4, "PDU type unknown"}, |
204 | | {5, "Unknown procedure"}, |
205 | | {6, "Unknown reserved value"}, |
206 | | {7, "Unknown field"}, |
207 | | {8, "Frame too short"}, |
208 | | {9, "Missing fields"}, |
209 | | {16, "Unexpected PDU type"}, |
210 | | {18, "Unexpected procedure"}, |
211 | | {19, "Unexpected RFCI"}, |
212 | | {20, "Unexpected value"}, |
213 | | {42, "Initialisation failure"}, |
214 | | {43, "Initialisation failure (network error, timer expiry)"}, |
215 | | {44, "Initialisation failure (Iu UP function error, repeated NACK)"}, |
216 | | {45, "Rate control failure"}, |
217 | | {46, "Error event failure"}, |
218 | | {47, "Time Alignment not supported"}, |
219 | | {48, "Requested Time Alignment not possible"}, |
220 | | {49, "Iu UP Mode version not supported"}, |
221 | | {0,NULL} |
222 | | }; |
223 | | |
224 | | static const value_string iuup_rfci_indicator[] = { |
225 | | {0, "RFCI allowed"}, |
226 | | {1, "RFCI barred"}, |
227 | | {0,NULL} |
228 | | }; |
229 | | |
230 | | |
231 | | static const value_string iuup_ti_vals[] = { |
232 | | {0, "IPTIs not present"}, |
233 | | {1, "IPTIs present in frame"}, |
234 | | {0,NULL} |
235 | | }; |
236 | | |
237 | | static const value_string iuup_mode_version_support[] = { |
238 | | {0, "not supported"}, |
239 | | {1, "supported"}, |
240 | | {0,NULL} |
241 | | }; |
242 | | |
243 | | static const value_string iuup_init_rfci_li_vals[] = { |
244 | | {0, "one octet used"}, |
245 | | {1, "two octets used"}, |
246 | | {0,NULL} |
247 | | }; |
248 | | |
249 | | static const value_string iuup_init_chain_ind_vals[] = { |
250 | | {0, "this frame is the last frame for the procedure"}, |
251 | | {1, "additional frames will be sent for the procedure"}, |
252 | | {0,NULL} |
253 | | }; |
254 | | |
255 | | static const value_string iuup_init_lri_vals[] = { |
256 | | {0, "Not last RFCI"}, |
257 | | {1, "Last RFCI in current frame"}, |
258 | | {0,NULL} |
259 | | }; |
260 | | |
261 | | static const value_string iuup_payload_pdu_type[] = { |
262 | | {0, "PDU type 0"}, |
263 | | {1, "PDU type 1"}, |
264 | | {0,NULL} |
265 | | }; |
266 | | |
267 | | static const value_string iuup_fqcs[] = { |
268 | | {0, "Frame Good"}, |
269 | | {1, "Frame BAD"}, |
270 | | {2, "Frame bad due to radio"}, |
271 | | {3, "spare"}, |
272 | | {0,NULL} |
273 | | }; |
274 | | |
275 | | |
276 | | static proto_item* |
277 | 0 | iuup_proto_tree_add_bits(packet_info *pinfo, proto_tree* tree, int hf, tvbuff_t* tvb, int offset, int bit_offset, unsigned bits, uint8_t** buf) { |
278 | 0 | static const uint8_t masks[] = {0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe}; |
279 | 0 | int len = (bits + bit_offset)/8 + (((bits + bit_offset)%8) ? 0 : 1); |
280 | 0 | uint8_t* shifted_buffer; |
281 | 0 | proto_item* pi; |
282 | 0 | int i; |
283 | |
|
284 | 0 | DISSECTOR_ASSERT(bit_offset < 8); |
285 | |
|
286 | 0 | shifted_buffer = (uint8_t *)tvb_memdup(pinfo->pool,tvb,offset,len+1); |
287 | |
|
288 | 0 | for(i = 0; i < len; i++) { |
289 | 0 | shifted_buffer[i] <<= bit_offset; |
290 | 0 | shifted_buffer[i] |= (shifted_buffer[i+1] & masks[bit_offset]) >> (8 - bit_offset); |
291 | 0 | } |
292 | |
|
293 | 0 | shifted_buffer[len] <<= bit_offset; |
294 | 0 | shifted_buffer[len] &= masks[(bits + bit_offset)%8]; |
295 | |
|
296 | 0 | if (buf) |
297 | 0 | *buf = shifted_buffer; |
298 | |
|
299 | 0 | pi = proto_tree_add_bytes(tree, hf, tvb, offset, len + (((bits + bit_offset)%8) ? 1 : 0) , shifted_buffer); |
300 | 0 | proto_item_append_text(pi, " (%i Bits)", bits); |
301 | |
|
302 | 0 | return pi; |
303 | 0 | } |
304 | | |
305 | | static iuup_circuit_t *find_iuup_circuit(packet_info *pinfo) |
306 | 0 | { |
307 | 0 | iuup_circuit_t *iuup_circuit; |
308 | 0 | conversation_t *p_conv; |
309 | |
|
310 | 0 | if (two_byte_pseudoheader) { |
311 | 0 | uint32_t circuit_id = conversation_get_id_from_elements(pinfo, CONVERSATION_IUUP, USE_LAST_ENDPOINT); |
312 | 0 | iuup_circuit = (iuup_circuit_t *)wmem_map_lookup(circuits,GUINT_TO_POINTER(circuit_id)); |
313 | 0 | return iuup_circuit; |
314 | 0 | } |
315 | | |
316 | 0 | p_conv = find_conversation(pinfo->num, |
317 | 0 | &pinfo->net_dst, &pinfo->net_src, |
318 | 0 | CONVERSATION_IUUP, |
319 | 0 | pinfo->destport, pinfo->srcport, 0); |
320 | 0 | if (!p_conv) |
321 | 0 | return NULL; |
322 | 0 | iuup_circuit = (iuup_circuit_t *)conversation_get_proto_data(p_conv, proto_iuup); |
323 | 0 | return iuup_circuit; |
324 | 0 | } |
325 | | |
326 | 0 | static void dissect_iuup_payload(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, unsigned rfci_id, int offset) { |
327 | 0 | iuup_circuit_t *iuup_circuit; |
328 | 0 | iuup_rfci_t *rfci; |
329 | 0 | int last_offset = tvb_reported_length(tvb) - 1; |
330 | 0 | unsigned bit_offset; |
331 | 0 | proto_item* pi; |
332 | |
|
333 | 0 | if (offset == (int)tvb_reported_length(tvb)) /* NO_DATA */ |
334 | 0 | return; |
335 | | |
336 | 0 | pi = proto_tree_add_item(tree,hf_iuup_payload,tvb,offset,-1,ENC_NA); |
337 | |
|
338 | 0 | if (!dissect_fields) |
339 | 0 | return; |
340 | 0 | if (!(iuup_circuit = find_iuup_circuit(pinfo))) { |
341 | 0 | expert_add_info(pinfo, pi, &ei_iuup_payload_undecoded); |
342 | 0 | return; |
343 | 0 | } |
344 | | |
345 | 0 | for(rfci = iuup_circuit->rfcis; rfci; rfci = rfci->next) |
346 | 0 | if ( rfci->id == rfci_id ) |
347 | 0 | break; |
348 | |
|
349 | 0 | if (!rfci) { |
350 | 0 | expert_add_info(pinfo, pi, &ei_iuup_payload_undecoded); |
351 | 0 | return; |
352 | 0 | } |
353 | | |
354 | 0 | tree = proto_item_add_subtree(pi,ett_payload); |
355 | | |
356 | |
|
357 | 0 | do { |
358 | 0 | unsigned i; |
359 | 0 | unsigned subflows = rfci->num_of_subflows; |
360 | 0 | proto_tree* flow_tree; |
361 | |
|
362 | 0 | flow_tree = proto_tree_add_subtree(tree,tvb,offset,-1,ett_payload_subflows,NULL,"Payload Frame"); |
363 | |
|
364 | 0 | bit_offset = 0; |
365 | |
|
366 | 0 | for(i = 0; i < subflows; i++) { |
367 | |
|
368 | 0 | if (! rfci->subflow[i].len) |
369 | 0 | continue; |
370 | | |
371 | 0 | iuup_proto_tree_add_bits(pinfo, flow_tree, hf_iuup_rfci_subflow[rfci->id][i], tvb, |
372 | 0 | offset + (bit_offset/8), |
373 | 0 | bit_offset % 8, |
374 | 0 | rfci->subflow[i].len, |
375 | 0 | NULL); |
376 | |
|
377 | 0 | bit_offset += rfci->subflow[i].len; |
378 | 0 | } |
379 | |
|
380 | 0 | if (bit_offset == 0) |
381 | 0 | break; |
382 | | |
383 | 0 | offset += (bit_offset / 8) + ((bit_offset % 8) ? 1 : 0); |
384 | |
|
385 | 0 | } while (offset <= last_offset); |
386 | 0 | } |
387 | | |
388 | 0 | static unsigned dissect_rfcis(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int* offset, iuup_circuit_t *iuup_circuit) { |
389 | 0 | proto_item* pi; |
390 | 0 | proto_tree* pt; |
391 | 0 | uint8_t oct; |
392 | 0 | unsigned c = 0; |
393 | 0 | unsigned i; |
394 | |
|
395 | 0 | DISSECTOR_ASSERT(iuup_circuit); |
396 | 0 | do { |
397 | 0 | iuup_rfci_t *rfci = wmem_new0(wmem_file_scope(), iuup_rfci_t); |
398 | 0 | unsigned len = 0; |
399 | |
|
400 | 0 | if (c >= 64) { |
401 | 0 | expert_add_info(pinfo, tree, &ei_iuup_too_many_rfcis); |
402 | 0 | break; |
403 | 0 | } |
404 | | |
405 | 0 | pi = proto_tree_add_item(tree,hf_iuup_init_rfci_ind,tvb,*offset,-1,ENC_NA); |
406 | 0 | pt = proto_item_add_subtree(pi,ett_rfci); |
407 | |
|
408 | 0 | proto_tree_add_item(pt,hf_iuup_init_rfci_lri[c],tvb,*offset,1,ENC_BIG_ENDIAN); |
409 | 0 | proto_tree_add_item(pt,hf_iuup_init_rfci_li[c],tvb,*offset,1,ENC_BIG_ENDIAN); |
410 | 0 | proto_tree_add_item(pt,hf_iuup_init_rfci[c],tvb,*offset,1,ENC_BIG_ENDIAN); |
411 | |
|
412 | 0 | oct = tvb_get_uint8(tvb,*offset); |
413 | 0 | rfci->id = oct & 0x3f; |
414 | 0 | rfci->num_of_subflows = iuup_circuit->num_of_subflows; |
415 | |
|
416 | 0 | len = (oct & 0x40) ? 2 : 1; |
417 | 0 | proto_item_set_text(pi,"RFCI %i Initialization",rfci->id); |
418 | 0 | proto_item_set_len(pi,(len*iuup_circuit->num_of_subflows)+1); |
419 | |
|
420 | 0 | (*offset)++; |
421 | |
|
422 | 0 | for(i = 0; i < iuup_circuit->num_of_subflows; i++) { |
423 | 0 | unsigned subflow_len; |
424 | |
|
425 | 0 | if (len == 2) { |
426 | 0 | subflow_len = tvb_get_ntohs(tvb,*offset); |
427 | 0 | } else { |
428 | 0 | subflow_len = tvb_get_uint8(tvb,*offset); |
429 | 0 | } |
430 | |
|
431 | 0 | rfci->subflow[i].len = subflow_len; |
432 | 0 | rfci->sum_len += subflow_len; |
433 | |
|
434 | 0 | proto_tree_add_uint(pt,hf_iuup_init_rfci_flow_len[c][i],tvb,*offset,len,subflow_len); |
435 | |
|
436 | 0 | (*offset) += len; |
437 | 0 | } |
438 | | |
439 | |
|
440 | 0 | if (iuup_circuit->last_rfci) { |
441 | 0 | iuup_circuit->last_rfci = iuup_circuit->last_rfci->next = rfci; |
442 | 0 | } else { |
443 | 0 | iuup_circuit->last_rfci = iuup_circuit->rfcis = rfci; |
444 | 0 | } |
445 | |
|
446 | 0 | c++; |
447 | 0 | } while ( ! (oct & 0x80) ); |
448 | |
|
449 | 0 | return c - 1; |
450 | 0 | } |
451 | | |
452 | 0 | static void dissect_iuup_init(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree) { |
453 | 0 | int offset = 4; |
454 | 0 | uint8_t oct = tvb_get_uint8(tvb,offset); |
455 | 0 | unsigned n = (oct & 0x0e) >> 1; |
456 | 0 | bool ti = oct & 0x10; |
457 | 0 | unsigned i; |
458 | 0 | unsigned rfcis; |
459 | 0 | proto_item* pi; |
460 | 0 | proto_tree* support_tree = NULL; |
461 | 0 | proto_tree* iptis_tree; |
462 | 0 | iuup_circuit_t *iuup_circuit = NULL; |
463 | 0 | uint32_t circuit_id = 0; |
464 | |
|
465 | 0 | if (two_byte_pseudoheader) { |
466 | 0 | iuup_circuit = find_iuup_circuit(pinfo); |
467 | 0 | if (iuup_circuit) { |
468 | 0 | circuit_id = iuup_circuit->id; |
469 | 0 | wmem_map_remove(circuits,GUINT_TO_POINTER(iuup_circuit->id)); |
470 | 0 | iuup_circuit = NULL; |
471 | 0 | } else { |
472 | 0 | circuit_id = conversation_get_id_from_elements(pinfo, CONVERSATION_IUUP, USE_LAST_ENDPOINT); |
473 | 0 | } |
474 | 0 | } |
475 | |
|
476 | 0 | iuup_circuit = wmem_new0(wmem_file_scope(), iuup_circuit_t); |
477 | 0 | iuup_circuit->id = circuit_id; |
478 | 0 | iuup_circuit->num_of_subflows = n; |
479 | 0 | iuup_circuit->rfcis = NULL; |
480 | 0 | iuup_circuit->last_rfci = NULL; |
481 | |
|
482 | 0 | if (two_byte_pseudoheader) { |
483 | 0 | wmem_map_insert(circuits,GUINT_TO_POINTER(circuit_id),iuup_circuit); |
484 | 0 | } else { |
485 | 0 | conversation_t *p_conv; |
486 | 0 | p_conv = conversation_new(pinfo->num, &pinfo->net_dst, &pinfo->net_src, CONVERSATION_IUUP, |
487 | 0 | pinfo->destport, pinfo->srcport, 0); |
488 | 0 | conversation_add_proto_data(p_conv, proto_iuup, iuup_circuit); |
489 | 0 | } |
490 | |
|
491 | 0 | if (tree) { |
492 | 0 | proto_tree_add_item(tree,hf_iuup_spare_e0,tvb,offset,1,ENC_BIG_ENDIAN); |
493 | 0 | proto_tree_add_item(tree,hf_iuup_init_ti,tvb,offset,1,ENC_BIG_ENDIAN); |
494 | 0 | proto_tree_add_item(tree,hf_iuup_init_subflows_per_rfci,tvb,offset,1,ENC_BIG_ENDIAN); |
495 | 0 | proto_tree_add_item(tree,hf_iuup_init_chain_ind,tvb,offset,1,ENC_BIG_ENDIAN); |
496 | 0 | } |
497 | |
|
498 | 0 | offset++; |
499 | |
|
500 | 0 | rfcis = dissect_rfcis(tvb, pinfo, tree, &offset, iuup_circuit); |
501 | |
|
502 | 0 | if (!tree) return; |
503 | | |
504 | 0 | if (ti) { |
505 | 0 | iptis_tree = proto_tree_add_subtree(tree,tvb,offset,(rfcis/2)+(rfcis%2),ett_ipti,NULL,"IPTIs"); |
506 | |
|
507 | 0 | for (i = 0; i <= rfcis; i++) { |
508 | 0 | proto_tree_add_item(iptis_tree,hf_iuup_init_ipti[i],tvb,offset,1,ENC_BIG_ENDIAN); |
509 | 0 | if ((i%2)) { |
510 | 0 | offset++; |
511 | 0 | } |
512 | 0 | } |
513 | |
|
514 | 0 | if ((i%2)) { |
515 | 0 | offset++; |
516 | 0 | } |
517 | 0 | } |
518 | |
|
519 | 0 | pi = proto_tree_add_item(tree,hf_iuup_mode_versions,tvb,offset,2,ENC_BIG_ENDIAN); |
520 | 0 | support_tree = proto_item_add_subtree(pi,ett_support); |
521 | |
|
522 | 0 | for (i = 0; i < 16; i++) { |
523 | 0 | proto_tree_add_item(support_tree,hf_iuup_mode_versions_a[i],tvb,offset,2,ENC_BIG_ENDIAN); |
524 | 0 | } |
525 | |
|
526 | 0 | offset += 2; |
527 | |
|
528 | 0 | proto_tree_add_item(tree,hf_iuup_data_pdu_type,tvb,offset,1,ENC_BIG_ENDIAN); |
529 | |
|
530 | 0 | } |
531 | | |
532 | 0 | static void dissect_iuup_ratectl(tvbuff_t* tvb, packet_info* pinfo _U_, proto_tree* tree) { |
533 | 0 | unsigned num = tvb_get_uint8(tvb,4) & 0x3f; |
534 | 0 | unsigned i; |
535 | 0 | proto_item* pi; |
536 | 0 | proto_tree* inds_tree; |
537 | 0 | int offset = 4; |
538 | |
|
539 | 0 | pi = proto_tree_add_item(tree,hf_iuup_num_rfci_ind,tvb,4,1,ENC_BIG_ENDIAN); |
540 | 0 | inds_tree = proto_item_add_subtree(pi,ett_rfciinds); |
541 | |
|
542 | 0 | for (i = 0; i < num; i++) { |
543 | 0 | if (! (i % 8) ) offset++; |
544 | 0 | proto_tree_add_item(inds_tree,hf_iuup_rfci_ratectl[i],tvb,offset,1,ENC_BIG_ENDIAN); |
545 | 0 | } |
546 | |
|
547 | 0 | } |
548 | | |
549 | | static void add_hdr_crc(tvbuff_t* tvb, packet_info* pinfo, proto_item* iuup_tree) |
550 | 0 | { |
551 | 0 | proto_tree_add_checksum(iuup_tree, tvb, 2, hf_iuup_hdr_crc, -1, &ei_iuup_hdr_crc_bad, |
552 | 0 | pinfo, crc6_compute_tvb(tvb, 2), ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY); |
553 | 0 | } |
554 | | |
555 | | static uint16_t |
556 | | update_crc10_by_bytes_iuup(tvbuff_t *tvb, int offset, int length) |
557 | 0 | { |
558 | 0 | uint16_t crc10; |
559 | 0 | uint16_t extra_16bits; |
560 | 0 | uint8_t extra_8bits[2]; |
561 | |
|
562 | 0 | crc10 = update_crc10_by_bytes_tvb(0, tvb, offset + 2, length); |
563 | 0 | extra_16bits = tvb_get_ntohs(tvb, offset) & 0x3FF; |
564 | 0 | extra_8bits[0] = extra_16bits >> 2; |
565 | 0 | extra_8bits[1] = (extra_16bits << 6) & 0xFF; |
566 | 0 | crc10 = update_crc10_by_bytes(crc10, extra_8bits, 2); |
567 | 0 | return crc10; |
568 | 0 | } |
569 | | |
570 | | static void add_payload_crc(tvbuff_t* tvb, packet_info* pinfo, proto_item* iuup_tree) |
571 | 0 | { |
572 | 0 | proto_item *crc_item; |
573 | 0 | int length = tvb_reported_length(tvb); |
574 | 0 | uint16_t crccheck = update_crc10_by_bytes_iuup(tvb, 2, length - 4); |
575 | |
|
576 | 0 | crc_item = proto_tree_add_item(iuup_tree,hf_iuup_payload_crc,tvb,2,2,ENC_BIG_ENDIAN); |
577 | 0 | if (crccheck) { |
578 | 0 | proto_item_append_text(crc_item, "%s", " [incorrect]"); |
579 | 0 | expert_add_info(pinfo, crc_item, &ei_iuup_payload_crc_bad); |
580 | 0 | } |
581 | 0 | } |
582 | | |
583 | | static int dissect_iuup_data(tvbuff_t* tvb, packet_info* pinfo, |
584 | | proto_tree* iuup_tree, void* data _U_, uint8_t pdutype) |
585 | 0 | { |
586 | 0 | proto_item *pi; |
587 | 0 | uint8_t first_octet; |
588 | 0 | uint8_t second_octet; |
589 | 0 | uint8_t payload_offset; |
590 | |
|
591 | 0 | first_octet = tvb_get_uint8(tvb,0); |
592 | 0 | second_octet = tvb_get_uint8(tvb,1); |
593 | |
|
594 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO,"FN: %x RFCI: %u", (unsigned)(first_octet & 0x0f), (unsigned)(second_octet & 0x3f)); |
595 | |
|
596 | 0 | proto_tree_add_item(iuup_tree,hf_iuup_frame_number,tvb,0,1,ENC_BIG_ENDIAN); |
597 | 0 | pi = proto_tree_add_item(iuup_tree,hf_iuup_fqc,tvb,1,1,ENC_BIG_ENDIAN); |
598 | |
|
599 | 0 | if (first_octet & FQC_MASK) { |
600 | 0 | expert_add_info(pinfo, pi, &ei_iuup_error_response); |
601 | 0 | } |
602 | |
|
603 | 0 | proto_tree_add_item(iuup_tree,hf_iuup_rfci,tvb,1,1,ENC_BIG_ENDIAN); |
604 | 0 | add_hdr_crc(tvb, pinfo, iuup_tree); |
605 | 0 | switch (pdutype) { |
606 | 0 | case PDUTYPE_DATA_WITH_CRC: |
607 | 0 | add_payload_crc(tvb, pinfo, iuup_tree); |
608 | 0 | payload_offset = 4; |
609 | 0 | break; |
610 | 0 | case PDUTYPE_DATA_NO_CRC: |
611 | 0 | payload_offset = 3; |
612 | 0 | break; |
613 | 0 | default: |
614 | 0 | DISSECTOR_ASSERT_NOT_REACHED(); |
615 | 0 | } |
616 | 0 | dissect_iuup_payload(tvb,pinfo,iuup_tree,second_octet & 0x3f, payload_offset); |
617 | 0 | return tvb_captured_length(tvb); |
618 | 0 | } |
619 | | |
620 | | static int dissect_iuup_control(tvbuff_t* tvb, packet_info* pinfo, |
621 | | proto_tree* iuup_tree, void* data _U_) |
622 | 0 | { |
623 | 0 | proto_item *pi; |
624 | 0 | proto_item *proc_item = NULL; |
625 | 0 | proto_item *ack_item = NULL; |
626 | 0 | uint8_t first_octet; |
627 | 0 | uint8_t second_octet; |
628 | |
|
629 | 0 | first_octet = tvb_get_uint8(tvb,0); |
630 | 0 | second_octet = tvb_get_uint8(tvb,1); |
631 | |
|
632 | 0 | if (iuup_tree) { |
633 | 0 | ack_item = proto_tree_add_item(iuup_tree,hf_iuup_ack_nack,tvb,0,1,ENC_BIG_ENDIAN); |
634 | 0 | proto_tree_add_item(iuup_tree,hf_iuup_frame_number_t14,tvb,0,1,ENC_BIG_ENDIAN); |
635 | 0 | proto_tree_add_item(iuup_tree,hf_iuup_mode_version,tvb,1,1,ENC_BIG_ENDIAN); |
636 | 0 | proc_item = proto_tree_add_item(iuup_tree,hf_iuup_procedure_indicator,tvb,1,1,ENC_BIG_ENDIAN); |
637 | 0 | add_hdr_crc(tvb, pinfo, iuup_tree); |
638 | 0 | } |
639 | |
|
640 | 0 | col_append_str(pinfo->cinfo, COL_INFO, |
641 | 0 | val_to_str(pinfo->pool, first_octet & ACKNACK_MASK, |
642 | 0 | iuup_colinfo_acknack_vals, "[action:%u] ")); |
643 | |
|
644 | 0 | col_append_str(pinfo->cinfo, COL_INFO, |
645 | 0 | val_to_str(pinfo->pool, second_octet & PROCEDURE_MASK, |
646 | 0 | iuup_colinfo_procedures, "[proc:%u] ")); |
647 | |
|
648 | 0 | switch ( first_octet & ACKNACK_MASK ) { |
649 | 0 | case ACKNACK_ACK: |
650 | 0 | switch(second_octet & PROCEDURE_MASK) { |
651 | 0 | case PROC_INIT: |
652 | 0 | proto_tree_add_item(iuup_tree,hf_iuup_spare_03,tvb,2,1,ENC_BIG_ENDIAN); |
653 | 0 | proto_tree_add_item(iuup_tree,hf_iuup_spare_ff,tvb,3,1,ENC_BIG_ENDIAN); |
654 | 0 | return tvb_captured_length(tvb); |
655 | 0 | case PROC_RATE: |
656 | 0 | dissect_iuup_ratectl(tvb,pinfo,iuup_tree); |
657 | 0 | return tvb_captured_length(tvb); |
658 | 0 | case PROC_TIME: |
659 | 0 | case PROC_ERROR: |
660 | 0 | break; |
661 | 0 | default: |
662 | 0 | expert_add_info(pinfo, proc_item, &ei_iuup_procedure_indicator); |
663 | 0 | return tvb_captured_length(tvb); |
664 | 0 | } |
665 | 0 | break; |
666 | 0 | case ACKNACK_NACK: |
667 | 0 | pi = proto_tree_add_item(iuup_tree,hf_iuup_error_cause_val,tvb,4,1,ENC_BIG_ENDIAN); |
668 | 0 | expert_add_info(pinfo, pi, &ei_iuup_error_response); |
669 | 0 | return tvb_captured_length(tvb); |
670 | 0 | case ACKNACK_RESERVED: |
671 | 0 | expert_add_info(pinfo, ack_item, &ei_iuup_ack_nack); |
672 | 0 | return tvb_captured_length(tvb); |
673 | 0 | case ACKNACK_PROC: |
674 | 0 | break; |
675 | 0 | } |
676 | | |
677 | 0 | switch( second_octet & PROCEDURE_MASK ) { |
678 | 0 | case PROC_INIT: |
679 | 0 | add_payload_crc(tvb, pinfo, iuup_tree); |
680 | 0 | dissect_iuup_init(tvb,pinfo,iuup_tree); |
681 | 0 | break; |
682 | 0 | case PROC_RATE: |
683 | 0 | add_payload_crc(tvb, pinfo, iuup_tree); |
684 | 0 | dissect_iuup_ratectl(tvb,pinfo,iuup_tree); |
685 | 0 | break; |
686 | 0 | case PROC_TIME: |
687 | 0 | { |
688 | 0 | proto_tree* time_tree; |
689 | 0 | unsigned ta; |
690 | |
|
691 | 0 | ta = tvb_get_uint8(tvb,4); |
692 | |
|
693 | 0 | pi = proto_tree_add_item(iuup_tree,hf_iuup_time_align,tvb,4,1,ENC_BIG_ENDIAN); |
694 | 0 | time_tree = proto_item_add_subtree(pi,ett_time); |
695 | |
|
696 | 0 | if (ta >= 1 && ta <= 80) { |
697 | 0 | pi = proto_tree_add_uint(time_tree,hf_iuup_delay,tvb,4,1,ta * 500); |
698 | 0 | proto_item_set_generated(pi); |
699 | 0 | pi = proto_tree_add_float(time_tree,hf_iuup_delta,tvb,4,1,((float)((int)(ta) * 500))/(float)1000000.0); |
700 | 0 | proto_item_set_generated(pi); |
701 | 0 | } else if (ta >= 129 && ta <= 208) { |
702 | 0 | pi = proto_tree_add_uint(time_tree,hf_iuup_advance,tvb,4,1,(ta-128) * 500); |
703 | 0 | proto_item_set_generated(pi); |
704 | 0 | pi = proto_tree_add_float(time_tree,hf_iuup_delta,tvb,4,1,((float)((int)(-(((int)ta)-128))) * 500)/(float)1000000.0); |
705 | 0 | proto_item_set_generated(pi); |
706 | 0 | } else { |
707 | 0 | expert_add_info(pinfo, pi, &ei_iuup_time_align); |
708 | 0 | } |
709 | |
|
710 | 0 | proto_tree_add_item(iuup_tree,hf_iuup_spare_bytes,tvb,5,-1,ENC_NA); |
711 | 0 | break; |
712 | 0 | } |
713 | 0 | case PROC_ERROR: |
714 | 0 | col_append_str(pinfo->cinfo, COL_INFO, val_to_str(pinfo->pool, tvb_get_uint8(tvb,4) & 0x3f,iuup_error_causes,"Unknown (%u)")); |
715 | |
|
716 | 0 | proto_tree_add_item(iuup_tree,hf_iuup_error_distance,tvb,4,1,ENC_BIG_ENDIAN); |
717 | 0 | pi = proto_tree_add_item(iuup_tree,hf_iuup_errorevt_cause_val,tvb,4,1,ENC_BIG_ENDIAN); |
718 | 0 | expert_add_info(pinfo, pi, &ei_iuup_error_response); |
719 | 0 | proto_tree_add_item(iuup_tree,hf_iuup_spare_bytes,tvb,5,-1,ENC_NA); |
720 | 0 | return tvb_captured_length(tvb); |
721 | 0 | default: /* bad */ |
722 | 0 | expert_add_info(pinfo, proc_item, &ei_iuup_procedure_indicator); |
723 | 0 | break; |
724 | 0 | } |
725 | 0 | return tvb_captured_length(tvb); |
726 | 0 | } |
727 | | |
728 | 0 | static int dissect_iuup(tvbuff_t *tvb_in, packet_info *pinfo, proto_tree *tree, void *data) { |
729 | 0 | proto_item* iuup_item = NULL; |
730 | 0 | proto_item* pdutype_item = NULL; |
731 | 0 | proto_tree* iuup_tree = NULL; |
732 | 0 | struct _rtp_info *rtp_info = NULL; |
733 | 0 | uint8_t first_octet; |
734 | 0 | uint8_t pdutype; |
735 | 0 | unsigned phdr = 0; |
736 | 0 | tvbuff_t* tvb = tvb_in; |
737 | |
|
738 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "IuUP"); |
739 | |
|
740 | 0 | if (two_byte_pseudoheader) { |
741 | 0 | int len = tvb_reported_length(tvb_in) - 2; |
742 | |
|
743 | 0 | phdr = tvb_get_ntohs(tvb,0); |
744 | |
|
745 | 0 | proto_tree_add_item(tree,hf_iuup_direction,tvb,0,2,ENC_BIG_ENDIAN); |
746 | 0 | proto_tree_add_item(tree,hf_iuup_circuit_id,tvb,0,2,ENC_BIG_ENDIAN); |
747 | |
|
748 | 0 | phdr &= 0x7fff; |
749 | |
|
750 | 0 | conversation_set_elements_by_id(pinfo, CONVERSATION_IUUP, phdr); |
751 | |
|
752 | 0 | tvb = tvb_new_subset_length(tvb_in,2,len); |
753 | 0 | } else if (data) { |
754 | | /* Coming from RTP */ |
755 | 0 | rtp_info = (struct _rtp_info*)data; |
756 | 0 | rtp_info->info_is_iuup = true; |
757 | 0 | } |
758 | |
|
759 | 0 | first_octet = tvb_get_uint8(tvb,0); |
760 | 0 | pdutype = ( first_octet & PDUTYPE_MASK ) >> 4; |
761 | |
|
762 | 0 | if (tree) { |
763 | 0 | iuup_item = proto_tree_add_item(tree,proto_iuup,tvb,0,-1,ENC_NA); |
764 | 0 | iuup_tree = proto_item_add_subtree(iuup_item,ett_iuup); |
765 | |
|
766 | 0 | pdutype_item = proto_tree_add_item(iuup_tree,hf_iuup_pdu_type,tvb,0,1,ENC_BIG_ENDIAN); |
767 | 0 | } |
768 | |
|
769 | 0 | col_add_str(pinfo->cinfo, COL_INFO, val_to_str(pinfo->pool, pdutype, iuup_colinfo_pdu_types, "Unknown PDU Type(%u) ")); |
770 | |
|
771 | 0 | switch(pdutype) { |
772 | 0 | case PDUTYPE_DATA_WITH_CRC: |
773 | 0 | case PDUTYPE_DATA_NO_CRC: |
774 | 0 | return dissect_iuup_data(tvb, pinfo, iuup_tree, data, pdutype); |
775 | 0 | case PDUTYPE_DATA_CONTROL_PROC: |
776 | 0 | return dissect_iuup_control(tvb, pinfo, iuup_tree, data); |
777 | 0 | default: |
778 | 0 | expert_add_info(pinfo, pdutype_item, &ei_iuup_pdu_type); |
779 | 0 | break; |
780 | 0 | } |
781 | 0 | return tvb_captured_length(tvb); |
782 | 0 | } |
783 | | |
784 | | |
785 | 0 | static bool dissect_iuup_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) { |
786 | 0 | int len = tvb_captured_length(tvb); |
787 | |
|
788 | 0 | if (len < 3) return false; |
789 | | |
790 | 0 | uint8_t first_octet = tvb_get_uint8(tvb,0); |
791 | 0 | uint8_t second_octet = tvb_get_uint8(tvb,1); |
792 | 0 | const uint8_t octet_array[] = {first_octet, second_octet}; |
793 | 0 | uint16_t hdrcrc6 = tvb_get_uint8(tvb, 2) >> 2; |
794 | |
|
795 | 0 | if (crc6_0X6F(hdrcrc6, octet_array, 2)) return false; |
796 | | |
797 | 0 | switch ( first_octet & 0xf0 ) { |
798 | 0 | case 0x00: { |
799 | 0 | if (len<7) return false; |
800 | 0 | if (update_crc10_by_bytes_iuup(tvb, 2, len-4) ) return false; |
801 | 0 | break; |
802 | 0 | } |
803 | 0 | case 0x10: |
804 | | /* a false positive factory */ |
805 | 0 | if (len<5) return false; |
806 | 0 | break; |
807 | 0 | case 0xe0: |
808 | 0 | if (len<5) return false; |
809 | 0 | if( (second_octet & 0x0f) > 3) return false; |
810 | 0 | break; |
811 | 0 | default: |
812 | 0 | return false; |
813 | 0 | } |
814 | | |
815 | 0 | dissect_iuup(tvb, pinfo, tree, data); |
816 | 0 | return true; |
817 | 0 | } |
818 | | |
819 | | |
820 | 0 | static int find_iuup(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { |
821 | 0 | int len = tvb_captured_length(tvb); |
822 | 0 | unsigned offset = 0; |
823 | |
|
824 | 0 | while (len > 3) { |
825 | 0 | if ( dissect_iuup_heur(tvb_new_subset_remaining(tvb,offset), pinfo, tree, data) ) |
826 | 0 | return tvb_captured_length(tvb); |
827 | | |
828 | 0 | offset++; |
829 | 0 | len--; |
830 | 0 | } |
831 | | |
832 | 0 | call_data_dissector(tvb, pinfo, tree); |
833 | 0 | return tvb_captured_length(tvb); |
834 | 0 | } |
835 | | |
836 | | |
837 | 16 | void proto_reg_handoff_iuup(void) { |
838 | 16 | dissector_add_string("rtp_dyn_payload_type","VND.3GPP.IUFP", iuup_handle); |
839 | | |
840 | 16 | dissector_add_uint_range_with_preference("rtp.pt", "", iuup_handle); |
841 | 16 | } |
842 | | |
843 | | |
844 | 1.02k | #define HFS_RFCI(i) \ |
845 | 1.02k | { &hf_iuup_rfci_ratectl[i], { "RFCI " #i, "iuup.rfci." #i, FT_UINT8, BASE_DEC, VALS(iuup_rfci_indicator),0x80>>(i%8),NULL,HFILL}}, \ |
846 | 1.02k | { &hf_iuup_init_rfci[i], { "RFCI " #i, "iuup.rfci." #i, FT_UINT8, BASE_DEC, NULL,0x3f,NULL,HFILL}}, \ |
847 | 1.02k | { &hf_iuup_init_rfci_flow_len[i][0], { "RFCI " #i " Flow 0 Len", "iuup.rfci."#i".flow.0.len", FT_UINT16, BASE_DEC, NULL,0x0,NULL,HFILL}}, \ |
848 | 1.02k | { &hf_iuup_init_rfci_flow_len[i][1], { "RFCI " #i " Flow 1 Len", "iuup.rfci."#i".flow.1.len", FT_UINT16, BASE_DEC, NULL,0x0,NULL,HFILL}}, \ |
849 | 1.02k | { &hf_iuup_init_rfci_flow_len[i][2], { "RFCI " #i " Flow 2 Len", "iuup.rfci."#i".flow.2.len", FT_UINT16, BASE_DEC, NULL,0x0,NULL,HFILL}}, \ |
850 | 1.02k | { &hf_iuup_init_rfci_flow_len[i][3], { "RFCI " #i " Flow 3 Len", "iuup.rfci."#i".flow.3.len", FT_UINT16, BASE_DEC, NULL,0x0,NULL,HFILL}}, \ |
851 | 1.02k | { &hf_iuup_init_rfci_flow_len[i][4], { "RFCI " #i " Flow 4 Len", "iuup.rfci."#i".flow.4.len", FT_UINT16, BASE_DEC, NULL,0x0,NULL,HFILL}}, \ |
852 | 1.02k | { &hf_iuup_init_rfci_flow_len[i][5], { "RFCI " #i " Flow 5 Len", "iuup.rfci."#i".flow.5.len", FT_UINT16, BASE_DEC, NULL,0x0,NULL,HFILL}}, \ |
853 | 1.02k | { &hf_iuup_init_rfci_flow_len[i][6], { "RFCI " #i " Flow 6 Len", "iuup.rfci."#i".flow.6.len", FT_UINT16, BASE_DEC, NULL,0x0,NULL,HFILL}}, \ |
854 | 1.02k | { &hf_iuup_init_rfci_flow_len[i][7], { "RFCI " #i " Flow 7 Len", "iuup.rfci."#i".flow.7.len", FT_UINT16, BASE_DEC, NULL,0x0,NULL,HFILL}}, \ |
855 | 1.02k | { &hf_iuup_init_rfci_li[i], { "RFCI " #i " LI", "iuup.rfci."#i".li", FT_UINT8, BASE_HEX, VALS(iuup_init_rfci_li_vals),0x40,"Length Indicator",HFILL}}, \ |
856 | 1.02k | { &hf_iuup_init_rfci_lri[i], { "RFCI " #i " LRI", "iuup.rfci."#i".lri", FT_UINT8, BASE_HEX, VALS(iuup_init_lri_vals),0x80,"Last Record Indicator",HFILL}}, \ |
857 | 1.02k | { &hf_iuup_rfci_subflow[i][0], { "RFCI " #i " Flow 0", "iuup.rfci."#i".flow.0", FT_BYTES, BASE_NONE, NULL,0x0,NULL,HFILL}}, \ |
858 | 1.02k | { &hf_iuup_rfci_subflow[i][1], { "RFCI " #i " Flow 1", "iuup.rfci."#i".flow.1", FT_BYTES, BASE_NONE, NULL,0x0,NULL,HFILL}}, \ |
859 | 1.02k | { &hf_iuup_rfci_subflow[i][2], { "RFCI " #i " Flow 2", "iuup.rfci."#i".flow.2", FT_BYTES, BASE_NONE, NULL,0x0,NULL,HFILL}}, \ |
860 | 1.02k | { &hf_iuup_rfci_subflow[i][3], { "RFCI " #i " Flow 3", "iuup.rfci."#i".flow.3", FT_BYTES, BASE_NONE, NULL,0x0,NULL,HFILL}}, \ |
861 | 1.02k | { &hf_iuup_rfci_subflow[i][4], { "RFCI " #i " Flow 4", "iuup.rfci."#i".flow.4", FT_BYTES, BASE_NONE, NULL,0x0,NULL,HFILL}}, \ |
862 | 1.02k | { &hf_iuup_rfci_subflow[i][5], { "RFCI " #i " Flow 5", "iuup.rfci."#i".flow.5", FT_BYTES, BASE_NONE, NULL,0x0,NULL,HFILL}}, \ |
863 | 1.02k | { &hf_iuup_rfci_subflow[i][6], { "RFCI " #i " Flow 6", "iuup.rfci."#i".flow.6", FT_BYTES, BASE_NONE, NULL,0x0,NULL,HFILL}}, \ |
864 | 1.02k | { &hf_iuup_rfci_subflow[i][7], { "RFCI " #i " Flow 7", "iuup.rfci."#i".flow.7", FT_BYTES, BASE_NONE, NULL,0x0,NULL,HFILL}}, \ |
865 | 1.02k | { &hf_iuup_init_ipti[i], { "RFCI " #i " IPTI", "iuup.rfci."#i".ipti", FT_UINT8, BASE_HEX, NULL,i%2 ? 0x0F : 0xF0,NULL,HFILL}} |
866 | | |
867 | | |
868 | | |
869 | 16 | void proto_register_iuup(void) { |
870 | 16 | static hf_register_info hf[] = { |
871 | 16 | { &hf_iuup_direction, { "Frame Direction", "iuup.direction", FT_UINT16, BASE_DEC, NULL,0x8000,NULL,HFILL}}, |
872 | 16 | { &hf_iuup_circuit_id, { "Circuit ID", "iuup.circuit_id", FT_UINT16, BASE_DEC, NULL,0x7fff,NULL,HFILL}}, |
873 | 16 | { &hf_iuup_pdu_type, { "PDU Type", "iuup.pdu_type", FT_UINT8, BASE_DEC, VALS(iuup_pdu_types),0xf0,NULL,HFILL}}, |
874 | 16 | { &hf_iuup_frame_number, { "Frame Number", "iuup.framenum", FT_UINT8, BASE_DEC, NULL,0x0F,NULL,HFILL}}, |
875 | 16 | { &hf_iuup_fqc, { "FQC", "iuup.fqc", FT_UINT8, BASE_DEC, VALS(iuup_fqcs),0xc0,"Frame Quality Classification",HFILL}}, |
876 | 16 | { &hf_iuup_rfci, { "RFCI", "iuup.rfci", FT_UINT8, BASE_HEX, NULL, 0x3f, "RAB sub-Flow Combination Indicator",HFILL}}, |
877 | 16 | { &hf_iuup_hdr_crc, { "Header CRC", "iuup.header_crc", FT_UINT8, BASE_HEX, NULL,0xfc,NULL,HFILL}}, |
878 | 16 | { &hf_iuup_payload_crc, { "Payload CRC", "iuup.payload_crc", FT_UINT16, BASE_HEX, NULL,0x03FF,NULL,HFILL}}, |
879 | 16 | { &hf_iuup_ack_nack, { "Ack/Nack", "iuup.ack", FT_UINT8, BASE_DEC, VALS(iuup_acknack_vals),0x0c,NULL,HFILL}}, |
880 | 16 | { &hf_iuup_frame_number_t14, { "Frame Number", "iuup.framenum_t14", FT_UINT8, BASE_DEC, NULL,0x03,NULL,HFILL}}, |
881 | 16 | { &hf_iuup_mode_version, { "Mode Version", "iuup.mode", FT_UINT8, BASE_HEX, NULL,0xf0,NULL,HFILL}}, |
882 | 16 | { &hf_iuup_procedure_indicator, { "Procedure", "iuup.procedure", FT_UINT8, BASE_DEC, VALS(iuup_procedures),0x0f,NULL,HFILL}}, |
883 | 16 | { &hf_iuup_error_cause_val, { "Error Cause", "iuup.error_cause", FT_UINT8, BASE_DEC, VALS(iuup_error_causes),0xfc,NULL,HFILL}}, |
884 | 16 | { &hf_iuup_error_distance, { "Error DISTANCE", "iuup.error_distance", FT_UINT8, BASE_DEC, VALS(iuup_error_distances),0xc0,NULL,HFILL}}, |
885 | 16 | { &hf_iuup_errorevt_cause_val, { "Error Cause", "iuup.errorevt_cause", FT_UINT8, BASE_DEC, NULL,0x3f,NULL,HFILL}}, |
886 | 16 | { &hf_iuup_time_align, { "Time Align", "iuup.time_align", FT_UINT8, BASE_HEX, NULL,0x0,NULL,HFILL}}, |
887 | 16 | { &hf_iuup_data_pdu_type, { "RFCI Data Pdu Type", "iuup.data_pdu_type", FT_UINT8, BASE_HEX, VALS(iuup_payload_pdu_type),0xF0,NULL,HFILL}}, |
888 | | |
889 | 16 | { &hf_iuup_spare_03, { "Spare", "iuup.spare", FT_UINT8, BASE_HEX, NULL,0x03,NULL,HFILL}}, |
890 | | #if 0 |
891 | | { &hf_iuup_spare_0f, { "Spare", "iuup.spare", FT_UINT8, BASE_HEX, NULL,0x0f,NULL,HFILL}}, |
892 | | #endif |
893 | | #if 0 |
894 | | { &hf_iuup_spare_c0, { "Spare", "iuup.spare", FT_UINT8, BASE_HEX, NULL,0xc0,NULL,HFILL}}, |
895 | | #endif |
896 | 16 | { &hf_iuup_spare_e0, { "Spare", "iuup.spare", FT_UINT8, BASE_HEX, NULL,0xe0,NULL,HFILL}}, |
897 | 16 | { &hf_iuup_spare_ff, { "Spare", "iuup.spare", FT_UINT8, BASE_HEX, NULL,0xff,NULL,HFILL}}, |
898 | 16 | { &hf_iuup_spare_bytes, { "Spare", "iuup.spare_bytes", FT_BYTES, BASE_NONE, NULL,0x0,NULL,HFILL}}, |
899 | | |
900 | 16 | { &hf_iuup_delay, { "Delay", "iuup.delay", FT_UINT32, BASE_HEX, NULL,0x0,NULL,HFILL}}, |
901 | 16 | { &hf_iuup_advance, { "Advance", "iuup.advance", FT_UINT32, BASE_HEX, NULL,0x0,NULL,HFILL}}, |
902 | 16 | { &hf_iuup_delta, { "Delta Time", "iuup.delta", FT_FLOAT, BASE_NONE, NULL,0x0,NULL,HFILL}}, |
903 | | |
904 | 16 | { &hf_iuup_init_ti, { "TI", "iuup.ti", FT_UINT8, BASE_DEC, VALS(iuup_ti_vals),0x10,"Timing Information",HFILL}}, |
905 | 16 | { &hf_iuup_init_subflows_per_rfci, { "Subflows", "iuup.subflows", FT_UINT8, BASE_DEC, NULL,0x0e,"Number of Subflows",HFILL}}, |
906 | 16 | { &hf_iuup_init_chain_ind, { "Chain Indicator", "iuup.chain_ind", FT_UINT8, BASE_DEC, VALS(iuup_init_chain_ind_vals),0x01,NULL,HFILL}}, |
907 | 16 | { &hf_iuup_payload, { "Payload Data", "iuup.payload_data", FT_BYTES, BASE_NONE, NULL,0x00,NULL,HFILL}}, |
908 | | |
909 | | |
910 | 16 | { &hf_iuup_mode_versions, { "Iu UP Mode Versions Supported", "iuup.support_mode", FT_UINT16, BASE_HEX, NULL,0x0,NULL,HFILL}}, |
911 | | |
912 | 16 | { &hf_iuup_mode_versions_a[ 0], { "Version 16", "iuup.support_mode.version16", FT_UINT16, BASE_HEX, VALS(iuup_mode_version_support),0x8000,NULL,HFILL}}, |
913 | 16 | { &hf_iuup_mode_versions_a[ 1], { "Version 15", "iuup.support_mode.version15", FT_UINT16, BASE_HEX, VALS(iuup_mode_version_support),0x4000,NULL,HFILL}}, |
914 | 16 | { &hf_iuup_mode_versions_a[ 2], { "Version 14", "iuup.support_mode.version14", FT_UINT16, BASE_HEX, VALS(iuup_mode_version_support),0x2000,NULL,HFILL}}, |
915 | 16 | { &hf_iuup_mode_versions_a[ 3], { "Version 13", "iuup.support_mode.version13", FT_UINT16, BASE_HEX, VALS(iuup_mode_version_support),0x1000,NULL,HFILL}}, |
916 | 16 | { &hf_iuup_mode_versions_a[ 4], { "Version 12", "iuup.support_mode.version12", FT_UINT16, BASE_HEX, VALS(iuup_mode_version_support),0x0800,NULL,HFILL}}, |
917 | 16 | { &hf_iuup_mode_versions_a[ 5], { "Version 11", "iuup.support_mode.version11", FT_UINT16, BASE_HEX, VALS(iuup_mode_version_support),0x0400,NULL,HFILL}}, |
918 | 16 | { &hf_iuup_mode_versions_a[ 6], { "Version 10", "iuup.support_mode.version10", FT_UINT16, BASE_HEX, VALS(iuup_mode_version_support),0x0200,NULL,HFILL}}, |
919 | 16 | { &hf_iuup_mode_versions_a[ 7], { "Version 9", "iuup.support_mode.version9", FT_UINT16, BASE_HEX, VALS(iuup_mode_version_support),0x0100,NULL,HFILL}}, |
920 | 16 | { &hf_iuup_mode_versions_a[ 8], { "Version 8", "iuup.support_mode.version8", FT_UINT16, BASE_HEX, VALS(iuup_mode_version_support),0x0080,NULL,HFILL}}, |
921 | 16 | { &hf_iuup_mode_versions_a[ 9], { "Version 7", "iuup.support_mode.version7", FT_UINT16, BASE_HEX, VALS(iuup_mode_version_support),0x0040,NULL,HFILL}}, |
922 | 16 | { &hf_iuup_mode_versions_a[10], { "Version 6", "iuup.support_mode.version6", FT_UINT16, BASE_HEX, VALS(iuup_mode_version_support),0x0020,NULL,HFILL}}, |
923 | 16 | { &hf_iuup_mode_versions_a[11], { "Version 5", "iuup.support_mode.version5", FT_UINT16, BASE_HEX, VALS(iuup_mode_version_support),0x0010,NULL,HFILL}}, |
924 | 16 | { &hf_iuup_mode_versions_a[12], { "Version 4", "iuup.support_mode.version4", FT_UINT16, BASE_HEX, VALS(iuup_mode_version_support),0x0008,NULL,HFILL}}, |
925 | 16 | { &hf_iuup_mode_versions_a[13], { "Version 3", "iuup.support_mode.version3", FT_UINT16, BASE_HEX, VALS(iuup_mode_version_support),0x0004,NULL,HFILL}}, |
926 | 16 | { &hf_iuup_mode_versions_a[14], { "Version 2", "iuup.support_mode.version2", FT_UINT16, BASE_HEX, VALS(iuup_mode_version_support),0x0002,NULL,HFILL}}, |
927 | 16 | { &hf_iuup_mode_versions_a[15], { "Version 1", "iuup.support_mode.version1", FT_UINT16, BASE_HEX, VALS(iuup_mode_version_support),0x0001,NULL,HFILL}}, |
928 | | |
929 | 16 | { &hf_iuup_num_rfci_ind, { "Number of RFCI Indicators", "iuup.p", FT_UINT8, BASE_HEX, NULL,0x3f,NULL,HFILL}}, |
930 | 16 | { &hf_iuup_init_rfci_ind, { "RFCI Initialization", "iuup.rfci.init", FT_BYTES, BASE_NONE, NULL,0x0,NULL,HFILL}}, |
931 | | |
932 | 16 | HFS_RFCI(0),HFS_RFCI(1),HFS_RFCI(2),HFS_RFCI(3),HFS_RFCI(4),HFS_RFCI(5),HFS_RFCI(6),HFS_RFCI(7), |
933 | 16 | HFS_RFCI(8),HFS_RFCI(9),HFS_RFCI(10),HFS_RFCI(11),HFS_RFCI(12),HFS_RFCI(13),HFS_RFCI(14),HFS_RFCI(15), |
934 | 16 | HFS_RFCI(16),HFS_RFCI(17),HFS_RFCI(18),HFS_RFCI(19),HFS_RFCI(20),HFS_RFCI(21),HFS_RFCI(22),HFS_RFCI(23), |
935 | 16 | HFS_RFCI(24),HFS_RFCI(25),HFS_RFCI(26),HFS_RFCI(27),HFS_RFCI(28),HFS_RFCI(29),HFS_RFCI(30),HFS_RFCI(31), |
936 | 16 | HFS_RFCI(32),HFS_RFCI(33),HFS_RFCI(34),HFS_RFCI(35),HFS_RFCI(36),HFS_RFCI(37),HFS_RFCI(38),HFS_RFCI(39), |
937 | 16 | HFS_RFCI(40),HFS_RFCI(41),HFS_RFCI(42),HFS_RFCI(43),HFS_RFCI(44),HFS_RFCI(45),HFS_RFCI(46),HFS_RFCI(47), |
938 | 16 | HFS_RFCI(48),HFS_RFCI(49),HFS_RFCI(50),HFS_RFCI(51),HFS_RFCI(52),HFS_RFCI(53),HFS_RFCI(54),HFS_RFCI(55), |
939 | 16 | HFS_RFCI(56),HFS_RFCI(57),HFS_RFCI(58),HFS_RFCI(59),HFS_RFCI(60),HFS_RFCI(61),HFS_RFCI(62),HFS_RFCI(63) |
940 | | |
941 | 16 | }; |
942 | | |
943 | | |
944 | 16 | int* ett[] = { |
945 | 16 | &ett_iuup, |
946 | 16 | &ett_rfci, |
947 | 16 | &ett_ipti, |
948 | 16 | &ett_support, |
949 | 16 | &ett_time, |
950 | 16 | &ett_rfciinds, |
951 | 16 | &ett_payload, |
952 | 16 | &ett_payload_subflows |
953 | 16 | }; |
954 | | |
955 | 16 | static ei_register_info ei[] = { |
956 | 16 | { &ei_iuup_hdr_crc_bad, { "iuup.hdr.crc.bad", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }}, |
957 | 16 | { &ei_iuup_payload_crc_bad, { "iuup.payload.crc.bad", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }}, |
958 | 16 | { &ei_iuup_payload_undecoded, { "iuup.payload.undecoded", PI_UNDECODED, PI_WARN, "Undecoded payload", EXPFILL }}, |
959 | 16 | { &ei_iuup_error_response, { "iuup.error_response", PI_RESPONSE_CODE, PI_ERROR, "Error response", EXPFILL }}, |
960 | 16 | { &ei_iuup_ack_nack, { "iuup.ack.malformed", PI_MALFORMED, PI_ERROR, "Malformed Ack/Nack", EXPFILL }}, |
961 | 16 | { &ei_iuup_time_align, { "iuup.time_align.malformed", PI_MALFORMED, PI_ERROR, "Malformed Time Align", EXPFILL }}, |
962 | 16 | { &ei_iuup_procedure_indicator, { "iuup.procedure.malformed", PI_MALFORMED, PI_ERROR, "Malformed Procedure", EXPFILL }}, |
963 | 16 | { &ei_iuup_too_many_rfcis, { "iuup.rfci.too_many", PI_MALFORMED, PI_ERROR, "Too many RFCIs (more than 64)", EXPFILL }}, |
964 | 16 | { &ei_iuup_pdu_type, { "iuup.pdu_type.malformed", PI_MALFORMED, PI_ERROR, "Malformed PDU Type", EXPFILL }}, |
965 | 16 | }; |
966 | | |
967 | 16 | module_t *iuup_module; |
968 | 16 | expert_module_t* expert_iuup; |
969 | | |
970 | 16 | proto_iuup = proto_register_protocol("IuUP", "IuUP", "iuup"); |
971 | 16 | proto_register_field_array(proto_iuup, hf, array_length(hf)); |
972 | 16 | proto_register_subtree_array(ett, array_length(ett)); |
973 | 16 | expert_iuup = expert_register_protocol(proto_iuup); |
974 | 16 | expert_register_field_array(expert_iuup, ei, array_length(ei)); |
975 | 16 | iuup_handle = register_dissector("iuup", dissect_iuup, proto_iuup); |
976 | 16 | register_dissector("find_iuup", find_iuup, proto_iuup); |
977 | | |
978 | 16 | circuits = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), g_direct_hash, g_direct_equal); |
979 | | |
980 | 16 | iuup_module = prefs_register_protocol(proto_iuup, NULL); |
981 | | |
982 | 16 | prefs_register_bool_preference(iuup_module, "dissect_payload", |
983 | 16 | "Dissect IuUP Payload bits", |
984 | 16 | "Whether IuUP Payload bits should be dissected", |
985 | 16 | &dissect_fields); |
986 | | |
987 | 16 | prefs_register_bool_preference(iuup_module, "two_byte_pseudoheader", |
988 | 16 | "Two byte pseudoheader", |
989 | 16 | "The payload contains a two byte pseudoheader indicating direction and circuit_id", |
990 | 16 | &two_byte_pseudoheader); |
991 | | |
992 | 16 | prefs_register_obsolete_preference(iuup_module, "dynamic.payload.type"); |
993 | 16 | } |
994 | | |
995 | | /* |
996 | | * Editor modelines |
997 | | * |
998 | | * Local Variables: |
999 | | * c-basic-offset: 4 |
1000 | | * tab-width: 8 |
1001 | | * indent-tabs-mode: nil |
1002 | | * End: |
1003 | | * |
1004 | | * ex: set shiftwidth=4 tabstop=8 expandtab: |
1005 | | * :indentSize=4:tabSize=8:noTabs=true: |
1006 | | */ |