Switch a bunch of dissectors over to using tvb_new_subset_remaining()
[obnox/wireshark/wip.git] / epan / dissectors / packet-erf.c
1 /* packet-erf.c
2  * Routines for ERF encapsulation dissection
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31
32 #include <glib.h>
33 #include <epan/packet.h>
34 #include <epan/expert.h>
35
36 /*
37 #include "wiretap/atm.h"
38 */
39 #include "wiretap/erf.h"
40 #include "epan/prefs.h"
41 #include "packet-erf.h"
42
43 /* Initialize the protocol and registered fields */
44 static int proto_erf        = -1;
45
46 static int hf_erf_ts   = -1;
47 static int hf_erf_types     = -1;
48 static int hf_erf_type      = -1;
49 static int hf_erf_ehdr      = -1;
50 static int hf_erf_ehdr_t      = -1;
51 static int hf_erf_flags     = -1;
52 static int hf_erf_flags_cap     = -1;
53 static int hf_erf_flags_vlen     = -1;
54 static int hf_erf_flags_trunc    = -1;
55 static int hf_erf_flags_rxe     = -1;
56 static int hf_erf_flags_dse     = -1;
57 static int hf_erf_flags_res     = -1;
58
59 static int hf_erf_rlen      = -1;
60 static int hf_erf_lctr      = -1;
61 static int hf_erf_wlen      = -1;
62
63 /* Classification extension header */
64
65 /* InterceptID extension header */
66 static int hf_erf_ehdr_int_res1 = -1;
67 static int hf_erf_ehdr_int_id = -1;
68 static int hf_erf_ehdr_int_res2 = -1;
69  
70 /* Raw Link extension header */
71 static int hf_erf_ehdr_raw_link_res = -1;
72 static int hf_erf_ehdr_raw_link_seqnum = -1;
73 static int hf_erf_ehdr_raw_link_rate = -1;
74 static int hf_erf_ehdr_raw_link_type = -1;
75
76 /* Classification extension header */
77 static int hf_erf_ehdr_class_flags = -1;
78 static int hf_erf_ehdr_class_flags_sh = -1;
79 static int hf_erf_ehdr_class_flags_shm = -1;
80 static int hf_erf_ehdr_class_flags_res1 = -1;
81 static int hf_erf_ehdr_class_flags_user = -1;
82 static int hf_erf_ehdr_class_flags_res2 = -1;
83 static int hf_erf_ehdr_class_flags_drop = -1;
84 static int hf_erf_ehdr_class_flags_str = -1;
85 static int hf_erf_ehdr_class_seqnum = -1;
86
87 /* Unknown extension header */
88 static int hf_erf_ehdr_unk = -1;
89
90 /* MC HDLC Header */
91 static int hf_erf_mc_hdlc_cn     = -1;
92 static int hf_erf_mc_hdlc_res1   = -1;
93 static int hf_erf_mc_hdlc_res2   = -1;
94 static int hf_erf_mc_hdlc_fcse   = -1;
95 static int hf_erf_mc_hdlc_sre    = -1;
96 static int hf_erf_mc_hdlc_lre    = -1;
97 static int hf_erf_mc_hdlc_afe    = -1;
98 static int hf_erf_mc_hdlc_oe     = -1;
99 static int hf_erf_mc_hdlc_lbe    = -1;
100 static int hf_erf_mc_hdlc_first  = -1;
101 static int hf_erf_mc_hdlc_res3   = -1;
102
103 /* MC RAW Header */
104 static int hf_erf_mc_raw_int   = -1;
105 static int hf_erf_mc_raw_res1  = -1;
106 static int hf_erf_mc_raw_res2  = -1;
107 static int hf_erf_mc_raw_res3  = -1;
108 static int hf_erf_mc_raw_sre   = -1;
109 static int hf_erf_mc_raw_lre   = -1;
110 static int hf_erf_mc_raw_res4  = -1;
111 static int hf_erf_mc_raw_lbe   = -1;
112 static int hf_erf_mc_raw_first = -1;
113 static int hf_erf_mc_raw_res5  = -1;
114
115 /* MC ATM Header */
116 static int hf_erf_mc_atm_cn   = -1;
117 static int hf_erf_mc_atm_res1 = -1;
118 static int hf_erf_mc_atm_mul  = -1;
119 static int hf_erf_mc_atm_port = -1;
120 static int hf_erf_mc_atm_res2 = -1;
121 static int hf_erf_mc_atm_lbe  = -1;
122 static int hf_erf_mc_atm_hec  = -1;
123 static int hf_erf_mc_atm_crc10   = -1;
124 static int hf_erf_mc_atm_oamcell = -1;
125 static int hf_erf_mc_atm_first   = -1;
126 static int hf_erf_mc_atm_res3    = -1;
127
128 /* MC Raw link Header */
129 static int hf_erf_mc_rawl_cn   = -1;
130 static int hf_erf_mc_rawl_res1 = -1;
131 static int hf_erf_mc_rawl_res2 = -1;
132 static int hf_erf_mc_rawl_lbe  = -1;
133 static int hf_erf_mc_rawl_first = -1;
134 static int hf_erf_mc_rawl_res3 = -1;
135
136 /* MC AAL5 Header */
137 static int hf_erf_mc_aal5_cn = -1;
138 static int hf_erf_mc_aal5_res1 = -1;
139 static int hf_erf_mc_aal5_port = -1;
140 static int hf_erf_mc_aal5_crcck = -1;
141 static int hf_erf_mc_aal5_crce = -1;
142 static int hf_erf_mc_aal5_lenck = -1;
143 static int hf_erf_mc_aal5_lene = -1;
144 static int hf_erf_mc_aal5_res2 = -1;
145 static int hf_erf_mc_aal5_first = -1;
146 static int hf_erf_mc_aal5_res3 = -1;
147
148 /* MC AAL2 Header */
149 static int hf_erf_mc_aal2_cn = -1;
150 static int hf_erf_mc_aal2_res1 = -1;
151 static int hf_erf_mc_aal2_res2 = -1;
152 static int hf_erf_mc_aal2_port = -1;
153 static int hf_erf_mc_aal2_res3 = -1;
154 static int hf_erf_mc_aal2_first = -1;
155 static int hf_erf_mc_aal2_maale = -1;
156 static int hf_erf_mc_aal2_lene = -1;
157 static int hf_erf_mc_aal2_cid = -1;
158
159 /* ERF Ethernet header/pad */
160 static int hf_erf_eth_off = -1;
161 static int hf_erf_eth_res1 = -1;
162
163 /* Initialize the subtree pointers */
164 static gint ett_erf = -1;
165 static gint ett_erf_pseudo_hdr = -1;
166 static gint ett_erf_types = -1;
167 static gint ett_erf_flags = -1;
168 static gint ett_erf_mc_hdlc = -1;
169 static gint ett_erf_mc_raw = -1;
170 static gint ett_erf_mc_atm = -1;
171 static gint ett_erf_mc_rawlink = -1;
172 static gint ett_erf_mc_aal5 = -1;
173 static gint ett_erf_mc_aal2 = -1;
174 static gint ett_erf_eth = -1;
175
176 /* Default subdissector, display raw hex data */
177 static dissector_handle_t data_handle;
178
179 /* IPv4 and IPv6 subdissectors */
180 static dissector_handle_t ipv4_handle;
181 static dissector_handle_t ipv6_handle;
182
183 static dissector_handle_t infiniband_handle;
184
185 typedef enum { 
186   ERF_HDLC_CHDLC = 0,
187   ERF_HDLC_PPP = 1,
188   ERF_HDLC_FRELAY = 2,
189   ERF_HDLC_MTP2 = 3,
190   ERF_HDLC_GUESS = 4,
191   ERF_HDLC_MAX = 5
192 } erf_hdlc_type_vals;
193 static gint erf_hdlc_type = ERF_HDLC_GUESS;
194 static dissector_handle_t chdlc_handle, ppp_handle, frelay_handle, mtp2_handle;
195
196 static gboolean erf_rawcell_first = FALSE;
197
198 typedef enum {
199   ERF_AAL5_GUESS = 0,
200   ERF_AAL5_LLC = 1
201 } erf_aal5_type_val;
202 static gint erf_aal5_type = ERF_AAL5_GUESS;
203 static dissector_handle_t atm_untruncated_handle;
204
205 static gboolean erf_ethfcs = TRUE;
206 static dissector_handle_t ethwithfcs_handle, ethwithoutfcs_handle;
207
208 /* Classification */
209 #define EHDR_CLASS_SH_MASK  0x800000
210 #define EHDR_CLASS_SHM_MASK 0x400000
211 #define EHDR_CLASS_RES1_MASK 0x300000
212 #define EHDR_CLASS_USER_MASK 0x0FFFF0
213 #define EHDR_CLASS_RES2_MASK 0x08
214 #define EHDR_CLASS_DROP_MASK 0x04
215 #define EHDR_CLASS_STER_MASK 0x03
216
217 /* Header for ATM traffic identification */
218 #define ATM_HDR_LENGTH 4
219
220 /* Multi Channel HDLC */
221 #define MC_HDLC_CN_MASK 0x03ff
222 #define MC_HDLC_RES1_MASK 0xfc00
223 #define MC_HDLC_RES2_MASK 0xff
224 #define MC_HDLC_FCSE_MASK 0x01
225 #define MC_HDLC_SRE_MASK 0x02
226 #define MC_HDLC_LRE_MASK 0x04
227 #define MC_HDLC_AFE_MASK 0x08
228 #define MC_HDLC_OE_MASK 0x10
229 #define MC_HDLC_LBE_MASK 0x20
230 #define MC_HDLC_FIRST_MASK 0x40
231 #define MC_HDLC_RES3_MASK 0x80
232
233 /* Multi Channel RAW */
234 #define MC_RAW_INT_MASK 0x0f
235 #define MC_RAW_RES1_MASK 0xf0
236 #define MC_RAW_RES2_MASK 0xffff
237 #define MC_RAW_RES3_MASK 0x01
238 #define MC_RAW_SRE_MASK 0x02
239 #define MC_RAW_LRE_MASK 0x04
240 #define MC_RAW_RES4_MASK 0x18
241 #define MC_RAW_LBE_MASK 0x20
242 #define MC_RAW_FIRST_MASK 0x40
243 #define MC_RAW_RES5_MASK 0x80
244
245 /* Multi Channel ATM */
246 #define MC_ATM_CN_MASK 0x03ff
247 #define MC_ATM_RES1_MASK 0x7c00
248 #define MC_ATM_MUL_MASK 0x8000
249 #define MC_ATM_PORT_MASK 0x0f
250 #define MC_ATM_RES2_MASK 0xf0
251 #define MC_ATM_LBE_MASK 0x01
252 #define MC_ATM_HEC_MASK 0x02
253 #define MC_ATM_CRC10_MASK 0x04
254 #define MC_ATM_OAMCELL_MASK 0x08
255 #define MC_ATM_FIRST_MASK 0x10
256 #define MC_ATM_RES3_MASK 0xe0
257
258 /* Multi Channel RAW Link */
259 #define MC_RAWL_CN_MASK 0x03ff
260 #define MC_RAWL_RES1_MASK 0xfffc
261 #define MC_RAWL_RES2_MASK 0x1f
262 #define MC_RAWL_LBE_MASK 0x20
263 #define MC_RAWL_FIRST_MASK 0x40
264 #define MC_RAWL_RES3_MASK 0x80
265
266 /* Multi Channel AAL5 */
267 #define MC_AAL5_CN_MASK 0x03ff
268 #define MC_AAL5_RES1_MASK 0xfc00
269 #define MC_AAL5_PORT_MASK 0x0f
270 #define MC_AAL5_CRCCK_MASK 0x10
271 #define MC_AAL5_CRCE_MASK 0x20
272 #define MC_AAL5_LENCK_MASK 0x40
273 #define MC_AAL5_LENE_MASK 0x80
274 #define MC_AAL5_RES2_MASK 0x0f
275 #define MC_AAL5_FIRST_MASK 0x10
276 #define MC_AAL5_RES3_MASK 0xe0
277
278 /* Multi Channel AAL2 */
279 #define MC_AAL2_CN_MASK 0x03ff
280 #define MC_AAL2_RES1_MASK 0x1c00
281 #define MC_AAL2_RES2_MASK 0xe000
282 #define MC_AAL2_PORT_MASK 0x0f
283 #define MC_AAL2_RES3_MASK 0x10
284 #define MC_AAL2_FIRST_MASK 0x20
285 #define MC_AAL2_MAALE_MASK 0x40
286 #define MC_AAL2_LENE_MASK 0x80
287 #define MC_AAL2_CID_MASK 0xff
288
289 /* ETH */
290 #define ETH_OFF_MASK 0xff
291 #define ETH_RES1_MASK 0xff
292
293 /* Record type defines */
294 static const value_string erf_type_vals[] = {
295   { ERF_TYPE_LEGACY,"LEGACY"},
296   { ERF_TYPE_HDLC_POS,"HDLC_POS"},
297   { ERF_TYPE_ETH,"ETH"},
298   { ERF_TYPE_ATM,"ATM"},
299   { ERF_TYPE_AAL5,"AAL5"}, 
300   { ERF_TYPE_MC_HDLC,"MC_HDLC"},
301   { ERF_TYPE_MC_RAW,"MC_RAW"},
302   { ERF_TYPE_MC_ATM,"MC_ATM"},
303   { ERF_TYPE_MC_RAW_CHANNEL,"MC_RAW_CHANNEL"},
304   { ERF_TYPE_MC_AAL5,"MC_AAL5"},
305   { ERF_TYPE_COLOR_HDLC_POS,"COLOR_HDLC_POS"},
306   { ERF_TYPE_COLOR_ETH,"COLOR_ETH"},
307   { ERF_TYPE_MC_AAL2,"MC_AAL2 "},
308   { ERF_TYPE_IP_COUNTER,"IP_COUNTER"},
309   { ERF_TYPE_TCP_FLOW_COUNTER,"TCP_FLOW_COUNTER"},
310   { ERF_TYPE_DSM_COLOR_HDLC_POS,"DSM_COLOR_HDLC_POS"},
311   { ERF_TYPE_DSM_COLOR_ETH,"DSM_COLOR_ETH "},
312   { ERF_TYPE_COLOR_MC_HDLC_POS,"COLOR_MC_HDLC_POS"},
313   { ERF_TYPE_AAL2,"AAL2"},
314   { ERF_TYPE_PAD,"PAD"},
315   { ERF_TYPE_INFINIBAND, "INFINIBAND"},
316   { ERF_TYPE_IPV4, "IPV4"},
317   { ERF_TYPE_IPV6, "IPV6"},
318   { ERF_TYPE_RAW_LINK, "RAW_LINK"},
319   {0, NULL}
320 };
321
322 /* Extended headers type defines */
323 static const value_string ehdr_type_vals[] = {
324   { EXT_HDR_TYPE_CLASSIFICATION, "Classification"},
325         { EXT_HDR_TYPE_INTERCEPTID, "InterceptID"},
326   { EXT_HDR_TYPE_RAW_LINK, "Raw Link"},
327         { 0, NULL }
328 };
329
330
331 static const value_string raw_link_types[] = {
332   { 0x00, "sonet"},
333   { 0x01, "sdh"},
334   { 0, NULL },
335 };
336
337 static const value_string raw_link_rates[] = {
338   { 0x00, "reserved"},
339   { 0x01, "oc3/stm1"},
340   { 0x02, "oc12/stm4"},
341   { 0x03, "oc48/stm16"},
342   { 0x04, "oc192/stm64"},
343   { 0, NULL },
344 };
345
346
347
348 /* Copy of atm_guess_traffic_type from atm.c in /wiretap */
349 static void
350 erf_atm_guess_lane_type(const guint8 *pd, guint len,
351     union wtap_pseudo_header *pseudo_header)
352 {
353         if (len >= 2) {
354                 if (pd[0] == 0xff && pd[1] == 0x00) {
355                         /*
356                          * Looks like LE Control traffic.
357                          */
358                         pseudo_header->atm.subtype = TRAF_ST_LANE_LE_CTRL;
359                 } else {
360                         /*
361                          * XXX - Ethernet, or Token Ring?
362                          * Assume Ethernet for now; if we see earlier
363                          * LANE traffic, we may be able to figure out
364                          * the traffic type from that, but there may
365                          * still be situations where the user has to
366                          * tell us.
367                          */
368                         pseudo_header->atm.subtype = TRAF_ST_LANE_802_3;
369                 }
370         }
371 }
372
373 static void
374 erf_atm_guess_traffic_type(const guint8 *pd, guint len,
375     union wtap_pseudo_header *pseudo_header)
376 {
377         /*
378          * Start out assuming nothing other than that it's AAL5.
379          */
380         pseudo_header->atm.aal = AAL_5;
381         pseudo_header->atm.type = TRAF_UNKNOWN;
382         pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
383
384         if (pseudo_header->atm.vpi == 0) {
385                 /*
386                  * Traffic on some PVCs with a VPI of 0 and certain
387                  * VCIs is of particular types.
388                  */
389                 switch (pseudo_header->atm.vci) {
390
391                 case 5:
392                         /*
393                          * Signalling AAL.
394                          */
395                         pseudo_header->atm.aal = AAL_SIGNALLING;
396                         return;
397
398                 case 16:
399                         /*
400                          * ILMI.
401                          */
402                         pseudo_header->atm.type = TRAF_ILMI;
403                         return;
404                 }
405         }
406
407         /*
408          * OK, we can't tell what it is based on the VPI/VCI; try
409          * guessing based on the contents, if we have enough data
410          * to guess.
411          */
412          
413         if (len >= 3) {
414                 if (pd[0] == 0xaa && pd[1] == 0xaa && pd[2] == 0x03) {
415                         /*
416                          * Looks like a SNAP header; assume it's LLC
417                          * multiplexed RFC 1483 traffic.
418                          */
419                         pseudo_header->atm.type = TRAF_LLCMX;
420                 } else if ((pseudo_header->atm.aal5t_len &&
421                         pseudo_header->atm.aal5t_len < 16) || len<16) {
422                         /*
423                          * As this cannot be a LANE Ethernet frame (less
424                          * than 2 bytes of LANE header + 14 bytes of
425                          * Ethernet header) we can try it as a SSCOP frame.
426                          */
427                         pseudo_header->atm.aal = AAL_SIGNALLING;
428                 } else if (pd[0] == 0x83 || pd[0] == 0x81) {
429                         /*
430                          * MTP3b headers often encapsulate
431                          * a SCCP or MTN in the 3G network.
432                          * This should cause 0x83 or 0x81
433                          * in the first byte.
434                          */
435                         pseudo_header->atm.aal = AAL_SIGNALLING;
436                 } else {
437                         /*
438                          * Assume it's LANE.
439                          */
440                         pseudo_header->atm.type = TRAF_LANE;
441                         erf_atm_guess_lane_type(pd, len, pseudo_header);
442                 }
443         } else {
444                /*
445                 * Not only VCI 5 is used for signaling. It might be
446                 * one of these VCIs.
447                 */
448                pseudo_header->atm.aal = AAL_SIGNALLING;
449         }
450 }
451
452 static void
453 dissect_classification_ex_header(tvbuff_t *tvb,  packet_info *pinfo, proto_tree *pseudo_hdr_tree, int idx)
454 {
455   proto_item *int_item= NULL, *flags_item = NULL;
456   proto_tree *int_tree = NULL, *flags_tree = NULL;
457   guint64 hdr = pinfo->pseudo_header->erf.ehdr_list[idx].ehdr;
458   guint32 value = (guint32)(hdr >> 32);
459   
460   if (pseudo_hdr_tree){
461     int_item = proto_tree_add_text(pseudo_hdr_tree, tvb, 0, 0, "Classification");
462     int_tree = proto_item_add_subtree(int_item, ett_erf_pseudo_hdr);  
463     PROTO_ITEM_SET_GENERATED(int_item);
464     
465     proto_tree_add_uint(int_tree, hf_erf_ehdr_t , tvb, 0, 0, (guint8)((hdr >> 56) & 0x7F));
466     flags_item=proto_tree_add_uint(int_tree, hf_erf_ehdr_class_flags, tvb, 0, 0, value & 0xFFFFFF);
467     flags_tree = proto_item_add_subtree(flags_item, hf_erf_ehdr_class_flags);
468
469     
470     proto_tree_add_uint(flags_tree, hf_erf_ehdr_class_flags_sh, tvb, 0, 0, value);
471     proto_tree_add_uint(flags_tree, hf_erf_ehdr_class_flags_shm, tvb, 0, 0,  value);
472     proto_tree_add_uint(flags_tree, hf_erf_ehdr_class_flags_res1, tvb, 0, 0, value);
473     proto_tree_add_uint(flags_tree, hf_erf_ehdr_class_flags_user, tvb, 0, 0, value);
474     proto_tree_add_uint(flags_tree, hf_erf_ehdr_class_flags_res2, tvb, 0, 0, value);
475     proto_tree_add_uint(flags_tree, hf_erf_ehdr_class_flags_drop, tvb, 0, 0, value);
476     proto_tree_add_uint(flags_tree, hf_erf_ehdr_class_flags_str, tvb, 0, 0, value);
477     proto_tree_add_uint(int_tree, hf_erf_ehdr_class_seqnum, tvb, 0, 0, (guint32)hdr);
478   }
479 }
480
481 static void
482 dissect_intercept_ex_header(tvbuff_t *tvb,  packet_info *pinfo, proto_tree *pseudo_hdr_tree, int idx)
483 {
484   proto_item *int_item= NULL;
485   proto_tree *int_tree = NULL;
486   guint64 hdr = pinfo->pseudo_header->erf.ehdr_list[idx].ehdr;
487   if (pseudo_hdr_tree){
488     int_item = proto_tree_add_text(pseudo_hdr_tree, tvb, 0, 0, "InterceptID");
489     int_tree = proto_item_add_subtree(int_item, ett_erf_pseudo_hdr);  
490     PROTO_ITEM_SET_GENERATED(int_item);
491     
492     proto_tree_add_uint(int_tree, hf_erf_ehdr_t , tvb, 0, 0, (guint8)((hdr >> 56) & 0x7F));
493     proto_tree_add_uint(int_tree, hf_erf_ehdr_int_res1, tvb, 0, 0, (guint8)((hdr >> 48) & 0xFF)); 
494     proto_tree_add_uint(int_tree, hf_erf_ehdr_int_id, tvb, 0, 0, (guint16)((hdr >> 32 ) & 0xFFFF)); 
495     proto_tree_add_uint(int_tree, hf_erf_ehdr_int_res2, tvb, 0, 0, (guint32)hdr); 
496   }
497 }
498
499 static void
500 dissect_raw_link_ex_header(tvbuff_t *tvb,  packet_info *pinfo, proto_tree *pseudo_hdr_tree, int idx)
501 {
502   proto_item *int_item= NULL;
503   proto_tree *int_tree = NULL;
504   guint64 hdr = pinfo->pseudo_header->erf.ehdr_list[idx].ehdr;
505   
506   if (pseudo_hdr_tree){
507     int_item = proto_tree_add_text(pseudo_hdr_tree, tvb, 0, 0, "Raw Link");
508     int_tree = proto_item_add_subtree(int_item, ett_erf_pseudo_hdr);  
509     PROTO_ITEM_SET_GENERATED(int_item);
510     
511     proto_tree_add_uint(int_tree, hf_erf_ehdr_t , tvb, 0, 0, (guint8)((hdr >> 56) & 0x7F));
512     proto_tree_add_uint(int_tree, hf_erf_ehdr_raw_link_res , tvb, 0, 0,  (guint32)((hdr >> 32) & 0xFFFFFF)); 
513     proto_tree_add_uint(int_tree, hf_erf_ehdr_raw_link_seqnum , tvb, 0, 0, (guint32)((hdr >> 16) & 0xffff));
514     proto_tree_add_uint(int_tree, hf_erf_ehdr_raw_link_rate, tvb, 0, 0, (guint32)((hdr >> 8) & 0x00ff));
515                 proto_tree_add_uint(int_tree, hf_erf_ehdr_raw_link_type, tvb, 0, 0, (guint32)(hdr & 0x00ff));
516   }
517 }
518
519 static void
520 dissect_unknown_ex_header(tvbuff_t *tvb,  packet_info *pinfo, proto_tree *pseudo_hdr_tree, int idx)
521 {
522   proto_item *unk_item= NULL;
523   proto_tree *unk_tree = NULL;
524   guint64 hdr = pinfo->pseudo_header->erf.ehdr_list[idx].ehdr;
525   
526   if (pseudo_hdr_tree){
527     unk_item = proto_tree_add_text(pseudo_hdr_tree, tvb, 0, 0, "Unknown");
528     unk_tree = proto_item_add_subtree(unk_item, ett_erf_pseudo_hdr);  
529     PROTO_ITEM_SET_GENERATED(unk_item);
530
531     proto_tree_add_uint(unk_tree, hf_erf_ehdr_t , tvb, 0, 0, (guint8)((hdr >> 56) & 0x7F));
532     proto_tree_add_uint64(unk_tree, hf_erf_ehdr_unk, tvb, 0, 0, hdr);
533   }
534 }
535
536 static void
537 dissect_mc_hdlc_header(tvbuff_t *tvb,  packet_info *pinfo, proto_tree *tree)
538
539   proto_item *mc_hdlc_item = NULL;
540   proto_tree *mc_hdlc_tree = NULL;
541   struct erf_mc_hdlc_hdrx * mc_hdlc;
542
543   if (tree) { 
544     mc_hdlc_item = proto_tree_add_text(tree, tvb, 0, 0, "Multi Channel HDLC Header");
545     mc_hdlc_tree = proto_item_add_subtree(mc_hdlc_item, ett_erf_mc_hdlc);  
546     PROTO_ITEM_SET_GENERATED(mc_hdlc_item);
547     mc_hdlc = (struct erf_mc_hdlc_hdrx *) (&pinfo->pseudo_header->erf.subhdr.mc_hdr);
548
549     proto_tree_add_uint(mc_hdlc_tree, hf_erf_mc_hdlc_cn, tvb, 0, 0,  mc_hdlc->byte01); 
550     proto_tree_add_uint(mc_hdlc_tree, hf_erf_mc_hdlc_res1, tvb, 0, 0,  mc_hdlc->byte01);
551     proto_tree_add_uint(mc_hdlc_tree, hf_erf_mc_hdlc_res2, tvb, 0, 0,  mc_hdlc->byte2);
552     proto_tree_add_uint(mc_hdlc_tree, hf_erf_mc_hdlc_fcse, tvb, 0, 0,  mc_hdlc->byte3);
553     proto_tree_add_uint(mc_hdlc_tree, hf_erf_mc_hdlc_sre,  tvb, 0, 0,  mc_hdlc->byte3);
554     proto_tree_add_uint(mc_hdlc_tree, hf_erf_mc_hdlc_lre,  tvb, 0, 0,  mc_hdlc->byte3);
555     proto_tree_add_uint(mc_hdlc_tree, hf_erf_mc_hdlc_afe,  tvb, 0, 0,  mc_hdlc->byte3);
556     proto_tree_add_uint(mc_hdlc_tree, hf_erf_mc_hdlc_oe,   tvb, 0, 0,  mc_hdlc->byte3);
557     proto_tree_add_uint(mc_hdlc_tree, hf_erf_mc_hdlc_lbe,  tvb, 0, 0,  mc_hdlc->byte3);
558     proto_tree_add_uint(mc_hdlc_tree, hf_erf_mc_hdlc_first, tvb, 0, 0,  mc_hdlc->byte3);
559     proto_tree_add_uint(mc_hdlc_tree, hf_erf_mc_hdlc_res3,  tvb, 0, 0,  mc_hdlc->byte3);
560   }
561 }
562
563 static void
564 dissect_mc_raw_header(tvbuff_t *tvb,  packet_info *pinfo, proto_tree *tree)
565
566   proto_item *mc_raw_item = NULL;
567   proto_tree *mc_raw_tree = NULL;
568   struct erf_mc_raw_hdrx * mc_raw;
569
570   if (tree) { 
571     mc_raw_item = proto_tree_add_text(tree, tvb, 0, 0, "Multi Channel RAW Header");
572     mc_raw_tree = proto_item_add_subtree(mc_raw_item, ett_erf_mc_raw);
573     PROTO_ITEM_SET_GENERATED(mc_raw_item);
574     mc_raw = (struct erf_mc_raw_hdrx *) (&pinfo->pseudo_header->erf.subhdr.mc_hdr);
575
576     proto_tree_add_uint(mc_raw_tree, hf_erf_mc_raw_int,  tvb, 0, 0, mc_raw->byte0);
577     proto_tree_add_uint(mc_raw_tree, hf_erf_mc_raw_res1, tvb, 0, 0, mc_raw->byte0);
578     proto_tree_add_uint(mc_raw_tree, hf_erf_mc_raw_res2, tvb, 0, 0, mc_raw->byte12);
579     proto_tree_add_uint(mc_raw_tree, hf_erf_mc_raw_res3, tvb, 0, 0, mc_raw->byte3);
580     proto_tree_add_uint(mc_raw_tree, hf_erf_mc_raw_sre, tvb, 0, 0, mc_raw->byte3);
581     proto_tree_add_uint(mc_raw_tree, hf_erf_mc_raw_lre,  tvb, 0, 0, mc_raw->byte3);
582     proto_tree_add_uint(mc_raw_tree, hf_erf_mc_raw_res4, tvb, 0, 0, mc_raw->byte3);
583     proto_tree_add_uint(mc_raw_tree, hf_erf_mc_raw_lbe, tvb, 0, 0, mc_raw->byte3);
584     proto_tree_add_uint(mc_raw_tree, hf_erf_mc_raw_first, tvb, 0, 0, mc_raw->byte3);
585     proto_tree_add_uint(mc_raw_tree, hf_erf_mc_raw_res5, tvb, 0, 0, mc_raw->byte3);
586   }
587 }
588
589 static void
590 dissect_mc_atm_header(tvbuff_t *tvb,  packet_info *pinfo, proto_tree *tree)
591
592   proto_item *mc_atm_item = NULL;
593   proto_tree *mc_atm_tree = NULL;
594   struct erf_mc_atm_hdrx * mc_atm;
595   
596   if (tree) { 
597     mc_atm_item = proto_tree_add_text(tree, tvb, 0, 0, "Multi Channel ATM Header");
598     mc_atm_tree = proto_item_add_subtree(mc_atm_item, ett_erf_mc_atm);
599     PROTO_ITEM_SET_GENERATED(mc_atm_item);
600     mc_atm = (struct erf_mc_atm_hdrx *) (&pinfo->pseudo_header->erf.subhdr.mc_hdr);
601
602     proto_tree_add_uint(mc_atm_tree, hf_erf_mc_atm_cn,   tvb, 0, 0, mc_atm->byte01);
603     proto_tree_add_uint(mc_atm_tree, hf_erf_mc_atm_res1, tvb, 0, 0, mc_atm->byte01);
604     proto_tree_add_uint(mc_atm_tree, hf_erf_mc_atm_mul,  tvb, 0, 0, mc_atm->byte01);
605
606     proto_tree_add_uint(mc_atm_tree, hf_erf_mc_atm_port, tvb, 0, 0, mc_atm->byte2);
607     proto_tree_add_uint(mc_atm_tree, hf_erf_mc_atm_res2, tvb, 0, 0, mc_atm->byte2);
608
609     proto_tree_add_uint(mc_atm_tree, hf_erf_mc_atm_lbe,     tvb, 0, 0, mc_atm->byte3);
610     proto_tree_add_uint(mc_atm_tree, hf_erf_mc_atm_hec,     tvb, 0, 0, mc_atm->byte3);
611     proto_tree_add_uint(mc_atm_tree, hf_erf_mc_atm_crc10,   tvb, 0, 0, mc_atm->byte3);
612     proto_tree_add_uint(mc_atm_tree, hf_erf_mc_atm_oamcell, tvb, 0, 0, mc_atm->byte3);
613     proto_tree_add_uint(mc_atm_tree, hf_erf_mc_atm_first,   tvb, 0, 0, mc_atm->byte3);
614     proto_tree_add_uint(mc_atm_tree, hf_erf_mc_atm_res3,    tvb, 0, 0, mc_atm->byte3);
615   }
616 }
617
618 static void
619 dissect_mc_rawlink_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
620
621   proto_item *mc_rawl_item = NULL;
622   proto_tree *mc_rawl_tree = NULL;
623   struct erf_mc_rawl_hdrx * mc_rawl;
624
625   if (tree) { 
626     mc_rawl_item = proto_tree_add_text(tree, tvb, 0, 0, "Multi Channel RAW Link Header");
627     mc_rawl_tree = proto_item_add_subtree(mc_rawl_item, ett_erf_mc_rawlink);
628     PROTO_ITEM_SET_GENERATED(mc_rawl_item);
629     mc_rawl = (struct erf_mc_rawl_hdrx *) (&pinfo->pseudo_header->erf.subhdr.mc_hdr);
630
631     proto_tree_add_uint(mc_rawl_tree, hf_erf_mc_rawl_cn, tvb, 0, 0, mc_rawl->byte01);
632     proto_tree_add_uint(mc_rawl_tree, hf_erf_mc_rawl_res2,  tvb, 0, 0, mc_rawl->byte3);
633     proto_tree_add_uint(mc_rawl_tree, hf_erf_mc_rawl_lbe,   tvb, 0, 0, mc_rawl->byte3);
634     proto_tree_add_uint(mc_rawl_tree, hf_erf_mc_rawl_first, tvb, 0, 0, mc_rawl->byte3);
635     proto_tree_add_uint(mc_rawl_tree, hf_erf_mc_rawl_res3,  tvb, 0, 0, mc_rawl->byte3);
636   }
637 }
638
639 static void
640 dissect_mc_aal5_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
641
642   proto_item *mc_aal5_item = NULL;
643   proto_tree *mc_aal5_tree = NULL;
644   struct erf_mc_aal5_hdrx * mc_aal5;
645
646   if (tree) { 
647     mc_aal5_item = proto_tree_add_text(tree, tvb, 0, 0, "Multi Channel AAL5 Header");
648     mc_aal5_tree = proto_item_add_subtree(mc_aal5_item, ett_erf_mc_aal5);
649     PROTO_ITEM_SET_GENERATED(mc_aal5_item);
650     mc_aal5 = (struct erf_mc_aal5_hdrx *) (&pinfo->pseudo_header->erf.subhdr.mc_hdr);
651
652     proto_tree_add_uint(mc_aal5_tree, hf_erf_mc_aal5_cn,   tvb, 0, 0, mc_aal5->byte01);
653     proto_tree_add_uint(mc_aal5_tree, hf_erf_mc_aal5_res1, tvb, 0, 0, mc_aal5->byte01);
654
655     proto_tree_add_uint(mc_aal5_tree, hf_erf_mc_aal5_port,  tvb, 0, 0, mc_aal5->byte2);
656     proto_tree_add_uint(mc_aal5_tree, hf_erf_mc_aal5_crcck, tvb, 0, 0, mc_aal5->byte2);
657     proto_tree_add_uint(mc_aal5_tree, hf_erf_mc_aal5_crce,  tvb, 0, 0, mc_aal5->byte2);
658     proto_tree_add_uint(mc_aal5_tree, hf_erf_mc_aal5_lenck, tvb, 0, 0, mc_aal5->byte2);
659     proto_tree_add_uint(mc_aal5_tree, hf_erf_mc_aal5_lene,  tvb, 0, 0, mc_aal5->byte2);
660
661     proto_tree_add_uint(mc_aal5_tree, hf_erf_mc_aal5_res2,  tvb, 0, 0, mc_aal5->byte3);
662     proto_tree_add_uint(mc_aal5_tree, hf_erf_mc_aal5_first, tvb, 0, 0, mc_aal5->byte3);
663     proto_tree_add_uint(mc_aal5_tree, hf_erf_mc_aal5_res3,  tvb, 0, 0, mc_aal5->byte3);
664   }
665 }
666
667 static void
668 dissect_mc_aal2_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
669
670   proto_item *mc_aal2_item = NULL;
671   proto_tree *mc_aal2_tree = NULL;
672   struct erf_mc_aal2_hdrx * mc_aal2;
673
674   if (tree) { 
675     mc_aal2_item = proto_tree_add_text(tree, tvb, 0, 0, "Multi Channel AAL2 Header");
676     mc_aal2_tree = proto_item_add_subtree(mc_aal2_item, ett_erf_mc_aal2);
677     PROTO_ITEM_SET_GENERATED(mc_aal2_item);
678     mc_aal2 = (struct erf_mc_aal2_hdrx *) (&pinfo->pseudo_header->erf.subhdr.mc_hdr);
679     
680     proto_tree_add_uint(mc_aal2_tree, hf_erf_mc_aal2_cn,   tvb, 0, 0, mc_aal2->byte01);
681     proto_tree_add_uint(mc_aal2_tree, hf_erf_mc_aal2_res1, tvb, 0, 0, mc_aal2->byte01);
682     proto_tree_add_uint(mc_aal2_tree, hf_erf_mc_aal2_res2, tvb, 0, 0, mc_aal2->byte01);
683
684     proto_tree_add_uint(mc_aal2_tree, hf_erf_mc_aal2_port, tvb, 0, 0, mc_aal2->byte2);
685     proto_tree_add_uint(mc_aal2_tree, hf_erf_mc_aal2_res3, tvb, 0, 0, mc_aal2->byte2);
686     proto_tree_add_uint(mc_aal2_tree, hf_erf_mc_aal2_first, tvb, 0, 0, mc_aal2->byte2);
687     proto_tree_add_uint(mc_aal2_tree, hf_erf_mc_aal2_maale, tvb, 0, 0, mc_aal2->byte2);
688     proto_tree_add_uint(mc_aal2_tree, hf_erf_mc_aal2_lene,  tvb, 0, 0, mc_aal2->byte2);
689
690     proto_tree_add_uint(mc_aal2_tree, hf_erf_mc_aal2_cid,    tvb, 0, 0, mc_aal2->byte3);
691   }
692 }
693
694 static void
695 dissect_eth_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
696
697   proto_item *eth_item = NULL;
698   proto_tree *eth_tree = NULL;
699   struct erf_eth_hdrx * eth_hdr;
700   
701   if (tree) { 
702     eth_item = proto_tree_add_text(tree, tvb, 0, 0, "Ethernet Header");
703     eth_tree = proto_item_add_subtree(eth_item, ett_erf_eth);
704     PROTO_ITEM_SET_GENERATED(eth_item);
705     eth_hdr = (struct erf_eth_hdrx *) (&pinfo->pseudo_header->erf.subhdr.eth_hdr);
706     
707     proto_tree_add_uint(eth_tree, hf_erf_eth_off, tvb, 0, 0, eth_hdr->byte0);
708     proto_tree_add_uint(eth_tree, hf_erf_eth_res1, tvb, 0, 0, eth_hdr->byte1);
709   }
710 }
711
712 static void
713 dissect_erf_pseudo_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
714 {  
715   proto_item *pi;
716   proto_item *pseudo_hdr_item = NULL, *flags_item = NULL, *types_item = NULL;
717   proto_tree *pseudo_hdr_tree = NULL, *flags_tree = NULL, *types_tree = NULL;
718
719   pseudo_hdr_item = proto_tree_add_text(tree, tvb, 0, 0, "ERF Header");
720   pseudo_hdr_tree = proto_item_add_subtree(pseudo_hdr_item, ett_erf_pseudo_hdr);
721   PROTO_ITEM_SET_GENERATED( pseudo_hdr_item);
722
723   pi=proto_tree_add_uint64(pseudo_hdr_tree, hf_erf_ts, tvb, 0, 0, pinfo->pseudo_header->erf.phdr.ts);
724
725   types_item = proto_tree_add_text(pseudo_hdr_tree, tvb, 0, 0, "Header type");
726   PROTO_ITEM_SET_GENERATED(types_item);
727
728   types_tree = proto_item_add_subtree(types_item, ett_erf_types);
729   pi=proto_tree_add_uint(types_tree, hf_erf_type, tvb, 0, 0, pinfo->pseudo_header->erf.phdr.type);
730   pi=proto_tree_add_uint(types_tree, hf_erf_ehdr, tvb, 0, 0, pinfo->pseudo_header->erf.phdr.type);
731
732   flags_item=proto_tree_add_uint(pseudo_hdr_tree, hf_erf_flags, tvb, 0, 0, pinfo->pseudo_header->erf.phdr.flags);
733   flags_tree = proto_item_add_subtree(flags_item, ett_erf_flags);
734   
735   pi=proto_tree_add_uint(flags_tree, hf_erf_flags_cap, tvb, 0, 0, pinfo->pseudo_header->erf.phdr.flags);
736   pi=proto_tree_add_uint(flags_tree, hf_erf_flags_vlen, tvb, 0, 0, pinfo->pseudo_header->erf.phdr.flags);
737   pi=proto_tree_add_uint(flags_tree, hf_erf_flags_trunc, tvb, 0, 0, pinfo->pseudo_header->erf.phdr.flags);
738   pi=proto_tree_add_uint(flags_tree, hf_erf_flags_rxe, tvb, 0, 0, pinfo->pseudo_header->erf.phdr.flags);
739   pi=proto_tree_add_uint(flags_tree, hf_erf_flags_dse, tvb, 0, 0, pinfo->pseudo_header->erf.phdr.flags);
740   pi=proto_tree_add_uint(flags_tree, hf_erf_flags_res, tvb, 0, 0, pinfo->pseudo_header->erf.phdr.flags);
741
742   pi=proto_tree_add_uint(pseudo_hdr_tree, hf_erf_rlen, tvb, 0, 0, pinfo->pseudo_header->erf.phdr.rlen);
743   pi=proto_tree_add_uint(pseudo_hdr_tree, hf_erf_lctr, tvb, 0, 0, pinfo->pseudo_header->erf.phdr.lctr);
744   if (pinfo->pseudo_header->erf.phdr.lctr > 0)
745           expert_add_info_format(pinfo, pi, PI_SEQUENCE, PI_WARN, "Packet loss occurred between previous and current packet");
746
747   pi=proto_tree_add_uint(pseudo_hdr_tree, hf_erf_wlen, tvb, 0, 0, pinfo->pseudo_header->erf.phdr.wlen);
748 }
749
750 static void
751 dissect_erf_pseudo_extension_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
752 {  
753   proto_item *pi;
754   proto_item *pseudo_hdr_item = NULL;
755   proto_tree *pseudo_hdr_tree = NULL;
756   guint8 type;
757   guint8 has_more = pinfo->pseudo_header->erf.phdr.type & 0x80;
758   int i = 0;
759   int max = sizeof(pinfo->pseudo_header->erf.ehdr_list)/sizeof(struct erf_ehdr);
760
761   pseudo_hdr_item = proto_tree_add_text(tree, tvb, 0, 0, "ERF Extension Headers");
762   pseudo_hdr_tree = proto_item_add_subtree(pseudo_hdr_item, ett_erf_pseudo_hdr);
763   PROTO_ITEM_SET_GENERATED(pseudo_hdr_item);
764
765   while(has_more && i < max){
766     type = (guint8) (pinfo->pseudo_header->erf.ehdr_list[i].ehdr >> 56);
767     
768     switch(type & 0x7f){
769     case EXT_HDR_TYPE_CLASSIFICATION: 
770       dissect_classification_ex_header(tvb, pinfo, pseudo_hdr_tree, i);
771       break;
772     case EXT_HDR_TYPE_INTERCEPTID: 
773       dissect_intercept_ex_header(tvb, pinfo, pseudo_hdr_tree, i);
774       break;
775     case EXT_HDR_TYPE_RAW_LINK:
776       dissect_raw_link_ex_header(tvb, pinfo, pseudo_hdr_tree, i);
777       break;
778     default:
779                         dissect_unknown_ex_header(tvb, pinfo, pseudo_hdr_tree, i);
780       break;
781     }
782     has_more = type & 0x80;
783     i++;
784   }
785   if (has_more){
786     pi = proto_tree_add_text(pseudo_hdr_tree, tvb, 0, 0, "More extension header present");
787     expert_add_info_format(pinfo, pi, PI_SEQUENCE, PI_WARN, "Some of the extension headers are not shown");
788   }
789
790 }
791
792 static void
793 dissect_erf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
794 {
795   guint8 flags;
796   guint8 erf_type;
797   guint32 atm_hdr=0;
798   proto_item *erf_item = NULL;
799   proto_tree *erf_tree = NULL;
800   guint atm_pdu_caplen;
801   const guint8 *atm_pdu;
802   erf_hdlc_type_vals hdlc_type;
803   guint8 first_byte;
804   tvbuff_t *new_tvb;
805
806   erf_type=pinfo->pseudo_header->erf.phdr.type & 0x7F;
807
808   col_set_str(pinfo->cinfo, COL_PROTOCOL, "ERF");
809   
810   if (check_col(pinfo->cinfo, COL_INFO)) {
811     col_add_fstr(pinfo->cinfo, COL_INFO, "%s",
812        val_to_str(erf_type, erf_type_vals, "Unknown type %u"));
813   }  
814
815   if (tree) {
816     erf_item = proto_tree_add_item(tree, proto_erf, tvb, 0, -1, FALSE);
817     erf_tree = proto_item_add_subtree(erf_item, ett_erf);
818   
819     dissect_erf_pseudo_header(tvb, pinfo, erf_tree);
820     if (pinfo->pseudo_header->erf.phdr.type & 0x80){
821         dissect_erf_pseudo_extension_header(tvb, pinfo, erf_tree);
822     }
823   }
824   
825   flags = pinfo->pseudo_header->erf.phdr.flags;
826   /*
827    * Set if frame is Received or Sent.
828    * XXX - this is really testing the low-order bit of the capture
829    * interface number, so interface 0 is assumed to be capturing
830    * in one direction on a bi-directional link, interface 1 is
831    * assumed to be capturing in the other direction on that link,
832    * and interfaces 2 and 3 are assumed to be capturing in two
833    * different directions on another link.  We don't distinguish
834    * between the two links.
835    */
836   pinfo->p2p_dir = ( (flags & 0x01) ? P2P_DIR_RECV : P2P_DIR_SENT);
837   
838   switch(erf_type) {
839
840   case ERF_TYPE_RAW_LINK:
841         call_dissector(data_handle, tvb, pinfo, erf_tree);
842         break;
843
844   case ERF_TYPE_IPV4:
845     if (ipv4_handle)
846       call_dissector(ipv4_handle, tvb, pinfo, erf_tree);
847     else
848       call_dissector(data_handle, tvb, pinfo, erf_tree);
849     break;
850
851   case ERF_TYPE_IPV6:
852     if (ipv6_handle)
853       call_dissector(ipv6_handle, tvb, pinfo, erf_tree);
854     else
855       call_dissector(data_handle, tvb, pinfo, erf_tree);
856     break;
857
858   case ERF_TYPE_INFINIBAND:
859     if (infiniband_handle)
860       call_dissector(infiniband_handle, tvb, pinfo, erf_tree);
861     else
862       call_dissector(data_handle, tvb, pinfo, erf_tree);
863     break;
864
865   case ERF_TYPE_LEGACY:
866   case ERF_TYPE_IP_COUNTER:
867   case ERF_TYPE_TCP_FLOW_COUNTER:
868     /* undefined */
869     break;
870
871   case ERF_TYPE_PAD:
872     /* Nothing to do */
873     break;
874       
875   case ERF_TYPE_MC_RAW:
876     dissect_mc_raw_header(tvb, pinfo, erf_tree);
877     if (data_handle)
878       call_dissector(data_handle, tvb, pinfo, tree);
879     break;
880       
881   case ERF_TYPE_MC_RAW_CHANNEL:
882     dissect_mc_rawlink_header(tvb, pinfo, erf_tree);
883     if (data_handle)
884       call_dissector(data_handle, tvb, pinfo, tree);
885     break;
886       
887   case ERF_TYPE_MC_ATM:
888     dissect_mc_atm_header(tvb, pinfo, erf_tree);
889     /* continue with type ATM */
890       
891   case ERF_TYPE_ATM:
892     memset(&pinfo->pseudo_header->atm, 0, sizeof(pinfo->pseudo_header->atm));
893     atm_hdr = tvb_get_ntohl(tvb, 0);
894     pinfo->pseudo_header->atm.vpi = ((atm_hdr & 0x0ff00000) >> 20);
895     pinfo->pseudo_header->atm.vci = ((atm_hdr & 0x000ffff0) >>  4);
896     pinfo->pseudo_header->atm.channel = (flags & 0x03);
897
898     new_tvb = tvb_new_subset_remaining(tvb, ATM_HDR_LENGTH);
899     /* Work around to have decoding working */
900     if (erf_rawcell_first) {
901       /* Treat this as a (short) ATM AAL5 PDU */
902       pinfo->pseudo_header->atm.aal = AAL_5;
903       switch (erf_aal5_type) {
904
905       case ERF_AAL5_GUESS:
906         pinfo->pseudo_header->atm.type = TRAF_UNKNOWN;
907         pinfo->pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
908         /* Try to guess the type according to the first bytes */
909         atm_pdu_caplen = tvb_length(new_tvb);
910         atm_pdu = tvb_get_ptr(new_tvb, 0, atm_pdu_caplen);
911         erf_atm_guess_traffic_type(atm_pdu, atm_pdu_caplen, pinfo->pseudo_header);
912         break;
913
914       case ERF_AAL5_LLC:
915         pinfo->pseudo_header->atm.type = TRAF_LLCMX;
916         pinfo->pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
917         break;
918       }
919
920       call_dissector(atm_untruncated_handle, new_tvb, pinfo, tree);
921     } else {
922       /* Treat this as a raw cell */
923       pinfo->pseudo_header->atm.flags |= ATM_RAW_CELL;
924       pinfo->pseudo_header->atm.aal = AAL_UNKNOWN;
925
926       call_dissector(data_handle, new_tvb, pinfo, tree);
927     }
928     break;
929
930   case ERF_TYPE_MC_AAL5:
931     dissect_mc_aal5_header(tvb, pinfo, erf_tree);
932     /* continue with type AAL5 */
933       
934   case ERF_TYPE_AAL5: 
935     atm_hdr = tvb_get_ntohl(tvb, 0);
936     memset(&pinfo->pseudo_header->atm, 0, sizeof(pinfo->pseudo_header->atm));
937     pinfo->pseudo_header->atm.vpi = ((atm_hdr & 0x0ff00000) >> 20);
938     pinfo->pseudo_header->atm.vci = ((atm_hdr & 0x000ffff0) >>  4);
939     pinfo->pseudo_header->atm.channel = (flags & 0x03);
940
941     new_tvb = tvb_new_subset_remaining(tvb, ATM_HDR_LENGTH);
942     /* Work around to have decoding working */
943     pinfo->pseudo_header->atm.aal = AAL_5;
944     switch (erf_aal5_type) {
945
946     case ERF_AAL5_GUESS:
947       pinfo->pseudo_header->atm.type = TRAF_UNKNOWN;
948       pinfo->pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
949       /* Try to guess the type according to the first bytes */
950       atm_pdu_caplen = tvb_length(new_tvb);
951       atm_pdu = tvb_get_ptr(new_tvb, 0, atm_pdu_caplen);
952       erf_atm_guess_traffic_type(atm_pdu, atm_pdu_caplen, pinfo->pseudo_header);
953       break;
954
955     case ERF_AAL5_LLC:
956       pinfo->pseudo_header->atm.type = TRAF_LLCMX;
957       pinfo->pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
958       break;
959     }
960
961     call_dissector(atm_untruncated_handle, new_tvb, pinfo, tree);
962     break;
963
964   case ERF_TYPE_MC_AAL2:
965     dissect_mc_aal2_header(tvb, pinfo, erf_tree);
966     /* continue with type AAL2 */
967
968   case ERF_TYPE_AAL2:
969     atm_hdr = tvb_get_ntohl(tvb, 0);
970     memset(&pinfo->pseudo_header->atm, 0, sizeof(pinfo->pseudo_header->atm));
971     pinfo->pseudo_header->atm.vpi = ((atm_hdr & 0x0ff00000) >> 20);
972     pinfo->pseudo_header->atm.vci = ((atm_hdr & 0x000ffff0) >>  4);
973     pinfo->pseudo_header->atm.channel = (flags & 0x03);
974     /* Work around to have decoding working */
975     pinfo->pseudo_header->atm.aal = AAL_2;
976     pinfo->pseudo_header->atm.type = TRAF_UNKNOWN;
977     pinfo->pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
978
979     new_tvb = tvb_new_subset_remaining(tvb, ATM_HDR_LENGTH);
980     call_dissector(atm_untruncated_handle, new_tvb, pinfo, tree);
981     break;
982
983   case ERF_TYPE_ETH:
984   case ERF_TYPE_COLOR_ETH:
985   case ERF_TYPE_DSM_COLOR_ETH:
986     dissect_eth_header(tvb, pinfo, erf_tree);
987     if (erf_ethfcs)
988       call_dissector(ethwithfcs_handle, tvb, pinfo, tree);
989     else
990       call_dissector(ethwithoutfcs_handle, tvb, pinfo, tree);
991     break;
992
993   case ERF_TYPE_MC_HDLC:
994     dissect_mc_hdlc_header(tvb, pinfo, erf_tree);
995     /* continue with type HDLC */
996       
997   case ERF_TYPE_HDLC_POS:
998   case ERF_TYPE_COLOR_HDLC_POS:
999   case ERF_TYPE_DSM_COLOR_HDLC_POS:
1000   case ERF_TYPE_COLOR_MC_HDLC_POS:
1001     hdlc_type = erf_hdlc_type;
1002
1003     if (hdlc_type == ERF_HDLC_GUESS) {
1004       /* Try to guess the type. */
1005       first_byte = tvb_get_guint8(tvb, 0);
1006       if (first_byte == 0x0f || first_byte == 0x8f)
1007         hdlc_type = ERF_HDLC_CHDLC;
1008       else {
1009         /* Anything to check for to recognize Frame Relay or MTP2?
1010            Should we require PPP packets to beging with FF 03? */
1011         hdlc_type = ERF_HDLC_PPP;
1012       }
1013     }
1014     /* Clean the pseudo header (if used in subdissector) and call the
1015        appropriate subdissector. */
1016     switch (hdlc_type) {
1017     case ERF_HDLC_CHDLC:
1018       call_dissector(chdlc_handle, tvb, pinfo, tree);
1019       break;
1020     case ERF_HDLC_PPP:
1021       call_dissector(ppp_handle, tvb, pinfo, tree);
1022       break;
1023     case ERF_HDLC_FRELAY: 
1024       memset(&pinfo->pseudo_header->x25, 0, sizeof(pinfo->pseudo_header->x25));
1025       call_dissector(frelay_handle, tvb, pinfo, tree);
1026       break;
1027     case ERF_HDLC_MTP2:
1028       /* not used, but .. */
1029       memset(&pinfo->pseudo_header->mtp2, 0, sizeof(pinfo->pseudo_header->mtp2));
1030       call_dissector(mtp2_handle, tvb, pinfo, tree);
1031       break;
1032     default:
1033       break;
1034     }
1035     break;
1036       
1037   default:
1038     break;
1039   } /* erf type */
1040 }
1041
1042 void
1043 proto_register_erf(void)
1044 {
1045
1046   static hf_register_info hf[] = {
1047     /* ERF Header */ 
1048     { &hf_erf_ts, { "Timestamp", "erf.ts", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL } },
1049     { &hf_erf_types, { "types", "erf.types", FT_UINT8, BASE_DEC,  NULL, 0xFF, NULL, HFILL } },
1050     { &hf_erf_type, { "type", "erf.types.type", FT_UINT8, BASE_DEC,  VALS(erf_type_vals), 0x7F, NULL, HFILL } },
1051     { &hf_erf_ehdr, { "Extension header present", "erf.types.ext_header", FT_UINT8, BASE_DEC,  NULL, 0x80, NULL, HFILL } },
1052     { &hf_erf_flags,{ "flags", "erf.flags", FT_UINT8, BASE_DEC, NULL, 0xFF, NULL, HFILL } },
1053     { &hf_erf_flags_cap,{ "capture interface", "erf.flags.cap", FT_UINT8, BASE_DEC, NULL, 0x03, NULL, HFILL } },
1054     { &hf_erf_flags_vlen,{ "varying record length", "erf.flags.vlen", FT_UINT8, BASE_DEC, NULL, 0x04, NULL, HFILL } },
1055     { &hf_erf_flags_trunc,{ "truncated", "erf.flags.trunc", FT_UINT8, BASE_DEC, NULL, 0x08, NULL, HFILL } },
1056     { &hf_erf_flags_rxe,{ "rx error", "erf.flags.rxe", FT_UINT8, BASE_DEC, NULL, 0x10, NULL, HFILL } },
1057     { &hf_erf_flags_dse,{ "ds error", "erf.flags.dse", FT_UINT8, BASE_DEC, NULL, 0x20, NULL, HFILL } },
1058     { &hf_erf_flags_res,{ "reserved", "erf.flags.res", FT_UINT8, BASE_DEC, NULL, 0xC0, NULL, HFILL } },
1059     { &hf_erf_rlen, { "record length", "erf.rlen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1060     { &hf_erf_lctr, { "loss counter", "erf.lctr", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1061     { &hf_erf_wlen, { "wire length", "erf.wlen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1062
1063                 { &hf_erf_ehdr_t, { "Extension Type", "erf.ehdr.types", FT_UINT8, BASE_DEC,  VALS(ehdr_type_vals), 0x0, NULL, HFILL } },
1064
1065     /* Intercept ID Extension Header */
1066     { &hf_erf_ehdr_int_res1, { "Reserved", "erf.ehdr.int.res1", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1067     { &hf_erf_ehdr_int_id, { "Intercept ID", "erf.ehdr.int.intid", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1068     { &hf_erf_ehdr_int_res2, { "Reserved", "erf.ehdr.int.res2", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1069
1070     /* Raw Link Extension Header */
1071     { &hf_erf_ehdr_raw_link_res, { "Reserved", "erf.ehdr.raw.res", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
1072     { &hf_erf_ehdr_raw_link_seqnum, { "Sequence number", "erf.ehdr.raw.seqnum", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1073     { &hf_erf_ehdr_raw_link_rate, { "Rate", "erf.ehdr.raw.rate", FT_UINT8, BASE_DEC, VALS(raw_link_rates), 0x0, NULL, HFILL } },
1074     { &hf_erf_ehdr_raw_link_type, { "Link Type", "erf.ehdr.raw.link_type", FT_UINT8, BASE_DEC, VALS(raw_link_types), 0x0, NULL, HFILL } },
1075
1076     /* Classification Extension Header */
1077     { &hf_erf_ehdr_class_flags, { "Flags", "erf.ehdr.class.flags", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1078     { &hf_erf_ehdr_class_flags_sh, { "Search hit", "erf.ehdr.class.flags.sh", FT_UINT32, BASE_DEC, NULL, EHDR_CLASS_SH_MASK, NULL, HFILL } },
1079     { &hf_erf_ehdr_class_flags_shm, { "Multiple search hits", "erf.ehdr.class.flags.shm", FT_UINT32, BASE_DEC, NULL, EHDR_CLASS_SHM_MASK, NULL, HFILL } },
1080     { &hf_erf_ehdr_class_flags_res1, { "Reserved", "erf.ehdr.class.flags.res1", FT_UINT32, BASE_DEC, NULL, EHDR_CLASS_RES1_MASK, NULL, HFILL } },
1081     { &hf_erf_ehdr_class_flags_user, { "User classification", "erf.ehdr.class.flags.user", FT_UINT32, BASE_DEC, NULL, EHDR_CLASS_USER_MASK, NULL, HFILL } },
1082     { &hf_erf_ehdr_class_flags_res2, { "Reserved", "erf.ehdr.class.flags.res2", FT_UINT32, BASE_DEC, NULL, EHDR_CLASS_RES2_MASK, NULL, HFILL } },
1083     { &hf_erf_ehdr_class_flags_drop, { "Drop Steering Bit", "erf.ehdr.class.flags.drop", FT_UINT32, BASE_DEC, NULL, EHDR_CLASS_DROP_MASK, NULL, HFILL } },
1084     { &hf_erf_ehdr_class_flags_str, { "Stream Steering Bits", "erf.ehdr.class.flags.str", FT_UINT32, BASE_DEC, NULL, EHDR_CLASS_STER_MASK, NULL, HFILL } },
1085     { &hf_erf_ehdr_class_seqnum, { "Sequence number", "erf.ehdr.class.seqnum", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1086
1087                 /* Unknown Extension Header */
1088                 { &hf_erf_ehdr_unk, { "Data", "erf.ehdr.unknown.data", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL } },
1089
1090     /* MC HDLC Header */
1091     { &hf_erf_mc_hdlc_cn,   { "connection number", "erf.mchdlc.cn", FT_UINT16, BASE_DEC, NULL, MC_HDLC_CN_MASK, NULL, HFILL } },
1092     { &hf_erf_mc_hdlc_res1, { "reserved", "erf.mchdlc.res1", FT_UINT16, BASE_DEC, NULL, MC_HDLC_RES1_MASK, NULL, HFILL } },
1093     { &hf_erf_mc_hdlc_res2, { "reserved", "erf.mchdlc.res2", FT_UINT8, BASE_DEC, NULL, MC_HDLC_RES2_MASK, NULL, HFILL } },
1094     { &hf_erf_mc_hdlc_fcse, { "FCS error", "erf.mchdlc.fcse", FT_UINT8, BASE_DEC, NULL, MC_HDLC_FCSE_MASK, NULL, HFILL } },
1095     { &hf_erf_mc_hdlc_sre,  { "Short record error", "erf.mchdlc.sre", FT_UINT8, BASE_DEC, NULL, MC_HDLC_SRE_MASK, NULL, HFILL } },
1096     { &hf_erf_mc_hdlc_lre,  { "Long record error", "erf.mchdlc.lre", FT_UINT8, BASE_DEC, NULL, MC_HDLC_LRE_MASK, NULL, HFILL } },
1097     { &hf_erf_mc_hdlc_afe,  { "Aborted frame error", "erf.mchdlc.afe", FT_UINT8, BASE_DEC, NULL, MC_HDLC_AFE_MASK, NULL, HFILL } },
1098     { &hf_erf_mc_hdlc_oe,   { "Octet error", "erf.mchdlc.oe", FT_UINT8, BASE_DEC, NULL, MC_HDLC_OE_MASK, NULL, HFILL } },
1099     { &hf_erf_mc_hdlc_lbe,  { "Lost byte error", "erf.mchdlc.lbe", FT_UINT8, BASE_DEC, NULL, MC_HDLC_LBE_MASK, NULL, HFILL } },
1100     { &hf_erf_mc_hdlc_first, { "First record", "erf.mchdlc.first", FT_UINT8, BASE_DEC, NULL, MC_HDLC_FIRST_MASK, NULL, HFILL } },
1101     { &hf_erf_mc_hdlc_res3, { "reserved", "erf.mchdlc.res3", FT_UINT8, BASE_DEC, NULL, MC_HDLC_RES3_MASK, NULL, HFILL } },
1102
1103     /* MC RAW Header */
1104     { &hf_erf_mc_raw_int,   { "physical interface", "erf.mcraw.int", FT_UINT8, BASE_DEC, NULL, MC_RAW_INT_MASK, NULL, HFILL } },
1105     { &hf_erf_mc_raw_res1, { "reserved", "erf.mcraw.res1", FT_UINT8, BASE_DEC, NULL, MC_RAW_RES1_MASK, NULL, HFILL } },
1106     { &hf_erf_mc_raw_res2, { "reserved", "erf.mcraw.res2", FT_UINT16, BASE_DEC, NULL, MC_RAW_RES2_MASK, NULL, HFILL } },
1107     { &hf_erf_mc_raw_res3, { "reserved", "erf.mcraw.res3", FT_UINT8, BASE_DEC, NULL, MC_RAW_RES3_MASK, NULL, HFILL } },
1108     { &hf_erf_mc_raw_sre,  { "Short record error", "erf.mcraw.sre", FT_UINT8, BASE_DEC, NULL, MC_RAW_SRE_MASK, NULL, HFILL } },
1109     { &hf_erf_mc_raw_lre,  { "Long record error", "erf.mcraw.lre", FT_UINT8, BASE_DEC, NULL, MC_RAW_LRE_MASK, NULL, HFILL } },
1110     { &hf_erf_mc_raw_res4,  { "reserved", "erf.mcraw.res4", FT_UINT8, BASE_DEC, NULL, MC_RAW_RES4_MASK, NULL, HFILL } },
1111     { &hf_erf_mc_raw_lbe,  { "Lost byte error", "erf.mcraw.lbe", FT_UINT8, BASE_DEC, NULL, MC_RAW_LBE_MASK, NULL, HFILL } },
1112     { &hf_erf_mc_raw_first, { "First record", "erf.mcraw.first", FT_UINT8, BASE_DEC, NULL, MC_RAW_FIRST_MASK, NULL, HFILL } },
1113     { &hf_erf_mc_raw_res5, { "reserved", "erf.mcraw.res5", FT_UINT8, BASE_DEC, NULL, MC_RAW_RES5_MASK, NULL, HFILL } },
1114
1115     /* MC ATM Header */
1116     { &hf_erf_mc_atm_cn,   { "connection number", "erf.mcatm.cn", FT_UINT16, BASE_DEC, NULL, MC_ATM_CN_MASK, NULL, HFILL } },
1117     { &hf_erf_mc_atm_res1, { "reserved", "erf.mcatm.res1", FT_UINT16, BASE_DEC, NULL, MC_ATM_RES1_MASK, NULL, HFILL } },
1118     { &hf_erf_mc_atm_mul,  { "multiplexed", "erf.mcatm.mul", FT_UINT16, BASE_DEC, NULL, MC_ATM_MUL_MASK, NULL, HFILL } },
1119     { &hf_erf_mc_atm_port, { "physical port", "erf.mcatm.port", FT_UINT8, BASE_DEC, NULL, MC_ATM_PORT_MASK, NULL, HFILL } },
1120     { &hf_erf_mc_atm_res2, { "reserved", "erf.mcatm.res2", FT_UINT8, BASE_DEC, NULL, MC_ATM_RES2_MASK, NULL, HFILL } },
1121     { &hf_erf_mc_atm_lbe,  { "Lost Byte Error", "erf.mcatm.lbe", FT_UINT8, BASE_DEC, NULL, MC_ATM_LBE_MASK, NULL, HFILL } },
1122     { &hf_erf_mc_atm_hec,  { "HEC corrected", "erf.mcatm.hec", FT_UINT8, BASE_DEC, NULL, MC_ATM_HEC_MASK, NULL, HFILL } },
1123     { &hf_erf_mc_atm_crc10, { "OAM Cell CRC10 Error (not implemented)", "erf.mcatm.crc10", FT_UINT8, BASE_DEC, NULL, MC_ATM_CRC10_MASK, NULL, HFILL } },
1124     { &hf_erf_mc_atm_oamcell,  { "OAM Cell", "erf.mcatm.oamcell", FT_UINT8, BASE_DEC, NULL, MC_ATM_OAMCELL_MASK, NULL, HFILL } },
1125     { &hf_erf_mc_atm_first, { "First record", "erf.mcatm.first", FT_UINT8, BASE_DEC, NULL, MC_ATM_FIRST_MASK, NULL, HFILL } },
1126     { &hf_erf_mc_atm_res3, { "reserved", "erf.mcatm.res3", FT_UINT8, BASE_DEC, NULL, MC_ATM_RES3_MASK, NULL, HFILL } },
1127
1128     /* MC RAW Link Header */
1129     { &hf_erf_mc_rawl_cn,   { "connection number", "erf.mcrawl.cn", FT_UINT8, BASE_DEC, NULL, MC_RAWL_CN_MASK, NULL, HFILL } },
1130     { &hf_erf_mc_rawl_res1, { "reserved", "erf.mcrawl.res1", FT_UINT16, BASE_DEC, NULL, MC_RAWL_RES1_MASK, NULL, HFILL } },
1131     { &hf_erf_mc_rawl_res2,  { "reserved", "erf.mcrawl.res2", FT_UINT8, BASE_DEC, NULL, MC_RAWL_RES2_MASK, NULL, HFILL } },
1132     { &hf_erf_mc_rawl_lbe,  { "Lost byte error", "erf.mcrawl.lbe", FT_UINT8, BASE_DEC, NULL, MC_RAWL_LBE_MASK, NULL, HFILL } },
1133     { &hf_erf_mc_rawl_first, { "First record", "erf.mcrawl.first", FT_UINT8, BASE_DEC, NULL, MC_RAWL_FIRST_MASK, NULL, HFILL } },
1134     { &hf_erf_mc_rawl_res3, { "reserved", "erf.mcrawl.res5", FT_UINT8, BASE_DEC, NULL, MC_RAWL_RES3_MASK, NULL, HFILL } },
1135
1136     /* MC AAL5 Header */
1137     { &hf_erf_mc_aal5_cn,   { "connection number", "erf.mcaal5.cn", FT_UINT16, BASE_DEC, NULL, MC_AAL5_CN_MASK, NULL, HFILL } },
1138     { &hf_erf_mc_aal5_res1, { "reserved", "erf.mcaal5.res1", FT_UINT16, BASE_DEC, NULL, MC_AAL5_RES1_MASK, NULL, HFILL } },
1139     { &hf_erf_mc_aal5_port, { "physical port", "erf.mcaal5.port", FT_UINT8, BASE_DEC, NULL, MC_AAL5_PORT_MASK, NULL, HFILL } },
1140     { &hf_erf_mc_aal5_crcck, { "CRC checked", "erf.mcaal5.crcck", FT_UINT8, BASE_DEC, NULL, MC_AAL5_CRCCK_MASK, NULL, HFILL } },
1141     { &hf_erf_mc_aal5_crce,  { "CRC error", "erf.mcaal5.crce", FT_UINT8, BASE_DEC, NULL, MC_AAL5_CRCE_MASK, NULL, HFILL } },
1142     { &hf_erf_mc_aal5_lenck,  { "Length checked", "erf.mcaal5.lenck", FT_UINT8, BASE_DEC, NULL, MC_AAL5_LENCK_MASK, NULL, HFILL } },
1143     { &hf_erf_mc_aal5_lene, { "Length error", "erf.mcaal5.lene", FT_UINT8, BASE_DEC, NULL, MC_AAL5_LENE_MASK, NULL, HFILL } },
1144     { &hf_erf_mc_aal5_res2,  { "reserved", "erf.mcaal5.res2", FT_UINT8, BASE_DEC, NULL, MC_AAL5_RES2_MASK, NULL, HFILL } },
1145     { &hf_erf_mc_aal5_first, { "First record", "erf.mcaal5.first", FT_UINT8, BASE_DEC, NULL, MC_AAL5_FIRST_MASK, NULL, HFILL } },
1146     { &hf_erf_mc_aal5_res3, { "reserved", "erf.mcaal5.res3", FT_UINT8, BASE_DEC, NULL, MC_AAL5_RES3_MASK, NULL, HFILL } },
1147
1148     /* MC AAL2 Header */
1149     { &hf_erf_mc_aal2_cn,   { "connection number", "erf.mcaal2.cn", FT_UINT16, BASE_DEC, NULL, MC_AAL2_CN_MASK, NULL, HFILL } },
1150     { &hf_erf_mc_aal2_res1, { "reserved for extra connection", "erf.mcaal2.res1", FT_UINT16, BASE_DEC, NULL, MC_AAL2_RES1_MASK, NULL, HFILL } },
1151     { &hf_erf_mc_aal2_res2,  { "reserved for type", "erf.mcaal2.mul", FT_UINT16, BASE_DEC, NULL, MC_AAL2_RES2_MASK, NULL, HFILL } },
1152     { &hf_erf_mc_aal2_port, { "physical port", "erf.mcaal2.port", FT_UINT8, BASE_DEC, NULL, MC_AAL2_PORT_MASK, NULL, HFILL } },
1153     { &hf_erf_mc_aal2_res3, { "reserved", "erf.mcaal2.res2", FT_UINT8, BASE_DEC, NULL, MC_AAL2_RES3_MASK, NULL, HFILL } },
1154     { &hf_erf_mc_aal2_first,  { "first cell received", "erf.mcaal2.lbe", FT_UINT8, BASE_DEC, NULL, MC_AAL2_FIRST_MASK, NULL, HFILL } },
1155     { &hf_erf_mc_aal2_maale,  { "MAAL error", "erf.mcaal2.hec", FT_UINT8, BASE_DEC, NULL, MC_AAL2_MAALE_MASK, NULL, HFILL } },
1156     { &hf_erf_mc_aal2_lene, { "Length error", "erf.mcaal2.crc10", FT_UINT8, BASE_DEC, NULL, MC_AAL2_LENE_MASK, NULL, HFILL } },
1157     { &hf_erf_mc_aal2_cid, { "Channel Identification Number", "erf.mcaal2.cid", FT_UINT8, BASE_DEC, NULL, MC_AAL2_CID_MASK, NULL, HFILL } },
1158
1159     /* ETH Header */
1160     { &hf_erf_eth_off,   { "offset", "erf.eth.off", FT_UINT8, BASE_DEC, NULL, ETH_OFF_MASK, NULL, HFILL } },
1161     { &hf_erf_eth_res1,   { "reserved", "erf.eth.res1", FT_UINT8, BASE_DEC, NULL, ETH_RES1_MASK, NULL, HFILL } },
1162
1163   };
1164
1165   static gint *ett[] = {
1166     &ett_erf,
1167     &ett_erf_pseudo_hdr,
1168     &ett_erf_types,
1169     &ett_erf_flags,
1170     &ett_erf_mc_hdlc,
1171     &ett_erf_mc_raw,
1172     &ett_erf_mc_atm,
1173     &ett_erf_mc_rawlink,
1174     &ett_erf_mc_aal5,
1175     &ett_erf_mc_aal2,
1176     &ett_erf_eth
1177   };
1178
1179   static enum_val_t erf_hdlc_options[] = { 
1180     { "chdlc",  "Cisco HDLC",       ERF_HDLC_CHDLC },
1181     { "ppp",    "PPP serial",       ERF_HDLC_PPP },
1182     { "frelay", "Frame Relay",      ERF_HDLC_FRELAY },
1183     { "mtp2",   "SS7 MTP2",         ERF_HDLC_MTP2 },
1184     { "guess",  "Attempt to guess", ERF_HDLC_GUESS },
1185     { NULL, NULL, 0 }
1186   };
1187
1188   static enum_val_t erf_aal5_options[] = { 
1189     { "guess", "Attempt to guess", ERF_AAL5_GUESS },
1190     { "llc",   "LLC multiplexed",  ERF_AAL5_LLC },
1191     { NULL, NULL, 0 }
1192   };
1193
1194   module_t *erf_module;
1195
1196   proto_erf = proto_register_protocol("Extensible Record Format", "ERF", "erf");
1197   register_dissector("erf", dissect_erf, proto_erf);
1198
1199   proto_register_field_array(proto_erf, hf, array_length(hf));
1200   proto_register_subtree_array(ett, array_length(ett));
1201   
1202   erf_module = prefs_register_protocol(proto_erf, NULL);
1203
1204   prefs_register_enum_preference(erf_module, "hdlc_type", "ERF_HDLC Layer 2",
1205                                  "Protocol encapsulated in HDLC records",
1206                                  &erf_hdlc_type, erf_hdlc_options, FALSE);
1207
1208   prefs_register_bool_preference(erf_module, "rawcell_first",
1209                                  "Raw ATM cells are first cell of AAL5 PDU",
1210                                  "Whether raw ATM cells should be treated as "
1211                                  "the first cell of an AAL5 PDU",
1212                                  &erf_rawcell_first);
1213
1214   prefs_register_enum_preference(erf_module, "aal5_type",
1215                                  "ATM AAL5 packet type",
1216                                  "Protocol encapsulated in ATM AAL5 packets",
1217                                  &erf_aal5_type, erf_aal5_options, FALSE);
1218
1219   prefs_register_bool_preference(erf_module, "ethfcs",
1220                                  "Ethernet packets have FCS",
1221                                  "Whether the FCS is present in Ethernet packets",
1222                                  &erf_ethfcs);
1223 }
1224
1225 void
1226 proto_reg_handoff_erf(void)
1227 {
1228   dissector_handle_t erf_handle;
1229
1230   erf_handle = find_dissector("erf");
1231   dissector_add("wtap_encap", WTAP_ENCAP_ERF, erf_handle);
1232
1233   /* Dissector called to dump raw data, or unknown protocol */
1234   data_handle = find_dissector("data");
1235
1236   /* Get handle for IP dissectors) */
1237   ipv4_handle = find_dissector("ip");
1238   ipv6_handle = find_dissector("ipv6");
1239
1240         
1241   /* Get handle for Infiniband dissector */
1242   infiniband_handle = find_dissector("infiniband");
1243
1244   /* Get handles for serial line protocols */
1245   chdlc_handle = find_dissector("chdlc");
1246   ppp_handle = find_dissector("ppp_hdlc");
1247   frelay_handle = find_dissector("fr");
1248   mtp2_handle = find_dissector("mtp2");
1249
1250   /* Get handle for ATM dissector */
1251   atm_untruncated_handle = find_dissector("atm_untruncated");
1252
1253   /* Get handles for Ethernet dissectors */
1254   ethwithfcs_handle = find_dissector("eth_withfcs");  
1255   ethwithoutfcs_handle = find_dissector("eth_withoutfcs");
1256 }