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