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