Use faster wmem_str* functions in a few places.
[metze/wireshark/wip.git] / epan / dissectors / packet-erf.c
1 /* packet-erf.c
2  * Routines for ERF encapsulation dissection
3  *
4  * Wireshark - Network traffic analyzer
5  * By Gerald Combs <gerald@wireshark.org>
6  * Copyright 1998 Gerald Combs
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22
23 #include "config.h"
24
25 #include <epan/packet.h>
26 #include <epan/expert.h>
27 #include <epan/prefs.h>
28 #include <epan/ipproto.h>
29 #include <epan/to_str.h>
30 #include <wsutil/str_util.h>
31 #include "packet-erf.h"
32
33 /*
34 */
35 #include "wiretap/erf.h"
36
37 void proto_register_erf(void);
38 void proto_reg_handoff_erf(void);
39
40 #define DECHAN_MAX_LINE_RATE 5
41 #define DECHAN_MAX_VC_SIZE 5
42 #define DECHAN_MAX_AUG_INDEX 4
43
44 typedef struct sdh_g707_format_s
45 {
46   guint8 m_sdh_line_rate;
47   guint8 m_vc_size ;
48   gint8 m_vc_index_array[DECHAN_MAX_AUG_INDEX];
49         /* i = 3 --> ITU-T letter #D - index of AUG-16
50          * i = 2 --> ITU-T letter #C - index of AUG-4,
51          * i = 1 --> ITU-T letter #B - index of AUG-1
52          * i = 0 --> ITU-T letter #A - index of AU3*/
53 } sdh_g707_format_t;
54
55 static dissector_handle_t erf_handle;
56 static dissector_table_t erf_dissector_table;
57
58 /* Initialize the protocol and registered fields */
59 static int proto_erf = -1;
60
61 static int hf_erf_ts          = -1;
62 static int hf_erf_rectype     = -1;
63 static int hf_erf_type        = -1;
64 static int hf_erf_ehdr        = -1;
65 static int hf_erf_ehdr_t      = -1;
66 static int hf_erf_flags       = -1;
67 static int hf_erf_flags_cap   = -1;
68 static int hf_erf_flags_vlen  = -1;
69 static int hf_erf_flags_trunc = -1;
70 static int hf_erf_flags_rxe   = -1;
71 static int hf_erf_flags_dse   = -1;
72 static int hf_erf_flags_res   = -1;
73
74 static int hf_erf_rlen = -1;
75 static int hf_erf_lctr = -1;
76 static int hf_erf_wlen = -1;
77
78 /* Classification extension header */
79
80 /* InterceptID extension header */
81 static int hf_erf_ehdr_int_res1 = -1;
82 static int hf_erf_ehdr_int_id   = -1;
83 static int hf_erf_ehdr_int_res2 = -1;
84
85 /* Raw Link extension header */
86 static int hf_erf_ehdr_raw_link_res    = -1;
87 static int hf_erf_ehdr_raw_link_seqnum = -1;
88 static int hf_erf_ehdr_raw_link_rate   = -1;
89 static int hf_erf_ehdr_raw_link_type   = -1;
90
91 /* Classification extension header */
92 static int hf_erf_ehdr_class_flags      = -1;
93 static int hf_erf_ehdr_class_flags_sh   = -1;
94 static int hf_erf_ehdr_class_flags_shm  = -1;
95 static int hf_erf_ehdr_class_flags_res1 = -1;
96 static int hf_erf_ehdr_class_flags_user = -1;
97 static int hf_erf_ehdr_class_flags_res2 = -1;
98 static int hf_erf_ehdr_class_flags_drop = -1;
99 static int hf_erf_ehdr_class_flags_str  = -1;
100 static int hf_erf_ehdr_class_seqnum     = -1;
101
102 /* BFS extension header */
103 static int hf_erf_ehdr_bfs_hash     = -1;
104 static int hf_erf_ehdr_bfs_color    = -1;
105 static int hf_erf_ehdr_bfs_raw_hash = -1;
106
107 /* Channelised extension header */
108 static int hf_erf_ehdr_chan_morebits                  = -1;
109 static int hf_erf_ehdr_chan_morefrag                  = -1;
110 static int hf_erf_ehdr_chan_seqnum                    = -1;
111 static int hf_erf_ehdr_chan_res                       = -1;
112 static int hf_erf_ehdr_chan_virt_container_id         = -1;
113 static int hf_erf_ehdr_chan_assoc_virt_container_size = -1;
114 static int hf_erf_ehdr_chan_rate                      = -1;
115 static int hf_erf_ehdr_chan_type                      = -1;
116
117 /* Filter Hash extension header */
118 static int hf_erf_ehdr_signature_payload_hash = -1;
119 static int hf_erf_ehdr_signature_color = -1;
120 static int hf_erf_ehdr_signature_flow_hash = -1;
121
122 /* Flow ID extension header */
123 static int hf_erf_ehdr_flow_id_source_id = -1;
124 static int hf_erf_ehdr_flow_id_hash_type = -1;
125 static int hf_erf_ehdr_flow_id_stack_type = -1;
126 static int hf_erf_ehdr_flow_id_flow_hash = -1;
127
128 /* Host ID extension header */
129 static int hf_erf_ehdr_host_id_sourceid          = -1;
130 static int hf_erf_ehdr_host_id_hostid            = -1;
131
132 /* Generated Host ID/Source ID */
133 static int hf_erf_sourceid       = -1;
134 static int hf_erf_hostid         = -1;
135 static int hf_erf_source_current = -1;
136 static int hf_erf_source_next    = -1;
137 static int hf_erf_source_prev    = -1;
138
139 /* Unknown extension header */
140 static int hf_erf_ehdr_unk = -1;
141
142 /* MC HDLC Header */
143 static int hf_erf_mc_hdlc        = -1;
144 static int hf_erf_mc_hdlc_cn     = -1;
145 static int hf_erf_mc_hdlc_res1   = -1;
146 static int hf_erf_mc_hdlc_res2   = -1;
147 static int hf_erf_mc_hdlc_fcse   = -1;
148 static int hf_erf_mc_hdlc_sre    = -1;
149 static int hf_erf_mc_hdlc_lre    = -1;
150 static int hf_erf_mc_hdlc_afe    = -1;
151 static int hf_erf_mc_hdlc_oe     = -1;
152 static int hf_erf_mc_hdlc_lbe    = -1;
153 static int hf_erf_mc_hdlc_first  = -1;
154 static int hf_erf_mc_hdlc_res3   = -1;
155
156 /* MC RAW Header */
157 static int hf_erf_mc_raw       = -1;
158 static int hf_erf_mc_raw_int   = -1;
159 static int hf_erf_mc_raw_res1  = -1;
160 static int hf_erf_mc_raw_sre   = -1;
161 static int hf_erf_mc_raw_lre   = -1;
162 static int hf_erf_mc_raw_res2  = -1;
163 static int hf_erf_mc_raw_lbe   = -1;
164 static int hf_erf_mc_raw_first = -1;
165 static int hf_erf_mc_raw_res3  = -1;
166
167 /* MC ATM Header */
168 static int hf_erf_mc_atm         = -1;
169 static int hf_erf_mc_atm_cn      = -1;
170 static int hf_erf_mc_atm_res1    = -1;
171 static int hf_erf_mc_atm_mul     = -1;
172 static int hf_erf_mc_atm_port    = -1;
173 static int hf_erf_mc_atm_res2    = -1;
174 static int hf_erf_mc_atm_lbe     = -1;
175 static int hf_erf_mc_atm_hec     = -1;
176 static int hf_erf_mc_atm_crc10   = -1;
177 static int hf_erf_mc_atm_oamcell = -1;
178 static int hf_erf_mc_atm_first   = -1;
179 static int hf_erf_mc_atm_res3    = -1;
180
181 /* MC Raw link Header */
182 static int hf_erf_mc_rawl       = -1;
183 static int hf_erf_mc_rawl_cn    = -1;
184 static int hf_erf_mc_rawl_res1  = -1;
185 static int hf_erf_mc_rawl_lbe   = -1;
186 static int hf_erf_mc_rawl_first = -1;
187 static int hf_erf_mc_rawl_res2  = -1;
188
189 /* MC AAL5 Header */
190 static int hf_erf_mc_aal5       = -1;
191 static int hf_erf_mc_aal5_cn    = -1;
192 static int hf_erf_mc_aal5_res1  = -1;
193 static int hf_erf_mc_aal5_port  = -1;
194 static int hf_erf_mc_aal5_crcck = -1;
195 static int hf_erf_mc_aal5_crce  = -1;
196 static int hf_erf_mc_aal5_lenck = -1;
197 static int hf_erf_mc_aal5_lene  = -1;
198 static int hf_erf_mc_aal5_res2  = -1;
199 static int hf_erf_mc_aal5_first = -1;
200 static int hf_erf_mc_aal5_res3  = -1;
201
202 /* MC AAL2 Header */
203 static int hf_erf_mc_aal2       = -1;
204 static int hf_erf_mc_aal2_cn    = -1;
205 static int hf_erf_mc_aal2_res1  = -1;
206 static int hf_erf_mc_aal2_res2  = -1;
207 static int hf_erf_mc_aal2_port  = -1;
208 static int hf_erf_mc_aal2_res3  = -1;
209 static int hf_erf_mc_aal2_first = -1;
210 static int hf_erf_mc_aal2_maale = -1;
211 static int hf_erf_mc_aal2_lene  = -1;
212 static int hf_erf_mc_aal2_cid   = -1;
213
214 /* AAL2 Header */
215 static int hf_erf_aal2        = -1;
216 static int hf_erf_aal2_cid    = -1;
217 static int hf_erf_aal2_maale  = -1;
218 static int hf_erf_aal2_maalei = -1;
219 static int hf_erf_aal2_first  = -1;
220 static int hf_erf_aal2_res1   = -1;
221
222 /* ERF Ethernet header/pad */
223 static int hf_erf_eth      = -1;
224 static int hf_erf_eth_off  = -1;
225 static int hf_erf_eth_pad  = -1;
226
227 /* ERF Meta record tag */
228 static int hf_erf_meta_tag_type   = -1;
229 static int hf_erf_meta_tag_len  = -1;
230 static int hf_erf_meta_tag_unknown  = -1;
231
232 /* Initialize the subtree pointers */
233 static gint ett_erf            = -1;
234 static gint ett_erf_pseudo_hdr = -1;
235 static gint ett_erf_rectype    = -1;
236 static gint ett_erf_flags      = -1;
237 static gint ett_erf_mc_hdlc    = -1;
238 static gint ett_erf_mc_raw     = -1;
239 static gint ett_erf_mc_atm     = -1;
240 static gint ett_erf_mc_rawlink = -1;
241 static gint ett_erf_mc_aal5    = -1;
242 static gint ett_erf_mc_aal2    = -1;
243 static gint ett_erf_aal2       = -1;
244 static gint ett_erf_eth        = -1;
245 static gint ett_erf_meta       = -1;
246 static gint ett_erf_meta_tag   = -1;
247 static gint ett_erf_source     = -1;
248
249 static expert_field ei_erf_extension_headers_not_shown = EI_INIT;
250 static expert_field ei_erf_packet_loss = EI_INIT;
251 static expert_field ei_erf_checksum_error = EI_INIT;
252 static expert_field ei_erf_meta_section_len_error = EI_INIT;
253 static expert_field ei_erf_meta_reset = EI_INIT;
254
255 typedef enum {
256   ERF_HDLC_CHDLC  = 0,
257   ERF_HDLC_PPP    = 1,
258   ERF_HDLC_FRELAY = 2,
259   ERF_HDLC_MTP2   = 3,
260   ERF_HDLC_GUESS  = 4,
261   ERF_HDLC_MAX    = 5
262 } erf_hdlc_type_vals;
263
264 static gint erf_hdlc_type = ERF_HDLC_GUESS;
265 static dissector_handle_t chdlc_handle, ppp_handle, frelay_handle, mtp2_handle;
266
267 static gboolean erf_rawcell_first = FALSE;
268
269 typedef enum {
270   ERF_AAL5_GUESS  = 0,
271   ERF_AAL5_LLC    = 1,
272   ERF_AAL5_UNSPEC = 2
273 } erf_aal5_type_val;
274
275 static gint erf_aal5_type = ERF_AAL5_GUESS;
276 static dissector_handle_t atm_untruncated_handle;
277
278 static gboolean erf_ethfcs = TRUE;
279
280 static dissector_handle_t sdh_handle;
281
282 /* ERF Header */
283 #define ERF_HDR_TYPE_MASK 0x7f
284 #define ERF_HDR_EHDR_MASK 0x80
285 #define ERF_HDR_FLAGS_MASK 0xff
286 #define ERF_HDR_CAP_MASK 0x03
287 #define ERF_HDR_VLEN_MASK 0x04
288 #define ERF_HDR_TRUNC_MASK 0x08
289 #define ERF_HDR_RXE_MASK 0x10
290 #define ERF_HDR_DSE_MASK 0x20
291 #define ERF_HDR_RES_MASK 0xC0
292
293 /* Classification */
294 #define EHDR_CLASS_FLAGS_MASK 0x00ffffff
295 #define EHDR_CLASS_SH_MASK    0x00800000
296 #define EHDR_CLASS_SHM_MASK   0x00400000
297 #define EHDR_CLASS_RES1_MASK  0x00300000
298 #define EHDR_CLASS_USER_MASK  0x000FFFF0
299 #define EHDR_CLASS_RES2_MASK  0x00000008
300 #define EHDR_CLASS_DROP_MASK  0x00000004
301 #define EHDR_CLASS_STER_MASK  0x00000003
302
303 /* Header for ATM traffic identification */
304 #define ATM_HDR_LENGTH 4
305
306 /* Multi Channel HDLC */
307 #define MC_HDLC_CN_MASK    0x000003ff
308 #define MC_HDLC_RES1_MASK  0x0000fc00
309 #define MC_HDLC_RES2_MASK  0x00ff0000
310 #define MC_HDLC_FCSE_MASK  0x01000000
311 #define MC_HDLC_SRE_MASK   0x02000000
312 #define MC_HDLC_LRE_MASK   0x04000000
313 #define MC_HDLC_AFE_MASK   0x08000000
314 #define MC_HDLC_OE_MASK    0x10000000
315 #define MC_HDLC_LBE_MASK   0x20000000
316 #define MC_HDLC_FIRST_MASK 0x40000000
317 #define MC_HDLC_RES3_MASK  0x80000000
318
319 /* Multi Channel RAW */
320 #define MC_RAW_INT_MASK   0x0000000f
321 #define MC_RAW_RES1_MASK  0x01fffff0
322 #define MC_RAW_SRE_MASK   0x02000000
323 #define MC_RAW_LRE_MASK   0x04000000
324 #define MC_RAW_RES2_MASK  0x18000000
325 #define MC_RAW_LBE_MASK   0x20000000
326 #define MC_RAW_FIRST_MASK 0x40000000
327 #define MC_RAW_RES3_MASK  0x80000000
328
329 /* Multi Channel ATM */
330 #define MC_ATM_CN_MASK      0x000003ff
331 #define MC_ATM_RES1_MASK    0x00007c00
332 #define MC_ATM_MUL_MASK     0x00008000
333 #define MC_ATM_PORT_MASK    0x000f0000
334 #define MC_ATM_RES2_MASK    0x00f00000
335 #define MC_ATM_LBE_MASK     0x01000000
336 #define MC_ATM_HEC_MASK     0x02000000
337 #define MC_ATM_CRC10_MASK   0x04000000
338 #define MC_ATM_OAMCELL_MASK 0x08000000
339 #define MC_ATM_FIRST_MASK   0x10000000
340 #define MC_ATM_RES3_MASK    0xe0000000
341
342 /* Multi Channel RAW Link */
343 #define MC_RAWL_CN_MASK    0x000003ff
344 #define MC_RAWL_RES1_MASK  0x1ffffc00
345 #define MC_RAWL_LBE_MASK   0x20000000
346 #define MC_RAWL_FIRST_MASK 0x40000000
347 #define MC_RAWL_RES2_MASK  0x80000000
348
349 /* Multi Channel AAL5 */
350 #define MC_AAL5_CN_MASK    0x000003ff
351 #define MC_AAL5_RES1_MASK  0x0000fc00
352 #define MC_AAL5_PORT_MASK  0x000f0000
353 #define MC_AAL5_CRCCK_MASK 0x00100000
354 #define MC_AAL5_CRCE_MASK  0x00200000
355 #define MC_AAL5_LENCK_MASK 0x00400000
356 #define MC_AAL5_LENE_MASK  0x00800000
357 #define MC_AAL5_RES2_MASK  0x0f000000
358 #define MC_AAL5_FIRST_MASK 0x10000000
359 #define MC_AAL5_RES3_MASK  0xe0000000
360
361 /* Multi Channel AAL2 */
362 #define MC_AAL2_CN_MASK    0x000003ff
363 #define MC_AAL2_RES1_MASK  0x00001c00
364 #define MC_AAL2_RES2_MASK  0x0000e000
365 #define MC_AAL2_PORT_MASK  0x000f0000
366 #define MC_AAL2_RES3_MASK  0x00100000
367 #define MC_AAL2_FIRST_MASK 0x00200000
368 #define MC_AAL2_MAALE_MASK 0x00400000
369 #define MC_AAL2_LENE_MASK  0x00800000
370 #define MC_AAL2_CID_MASK   0xff000000
371 #define MC_AAL2_CID_SHIFT  24
372
373 /* AAL2 */
374 #define AAL2_CID_MASK    0x000000ff
375 #define AAL2_CID_SHIFT   0
376 #define AAL2_MAALE_MASK  0x0000ff00
377 #define AAL2_MAALEI_MASK 0x00010000
378 #define AAL2_FIRST_MASK  0x00020000
379 #define AAL2_RES1_MASK   0xfffc0000
380
381 /* ETH */
382 #define ETH_OFF_MASK  0x00
383 #define ETH_RES1_MASK 0x00
384
385 /* Invalid MetaERF sections used for special lookup */
386 #define ERF_META_SECTION_NONE 0
387 #define ERF_META_SECTION_UNKNOWN 1
388
389 /* Record type defines */
390 static const value_string erf_type_vals[] = {
391   { ERF_TYPE_LEGACY             ,"LEGACY"},
392   { ERF_TYPE_HDLC_POS           ,"HDLC_POS"},
393   { ERF_TYPE_ETH                ,"ETH"},
394   { ERF_TYPE_ATM                ,"ATM"},
395   { ERF_TYPE_AAL5               ,"AAL5"},
396   { ERF_TYPE_MC_HDLC            ,"MC_HDLC"},
397   { ERF_TYPE_MC_RAW             ,"MC_RAW"},
398   { ERF_TYPE_MC_ATM             ,"MC_ATM"},
399   { ERF_TYPE_MC_RAW_CHANNEL     ,"MC_RAW_CHANNEL"},
400   { ERF_TYPE_MC_AAL5            ,"MC_AAL5"},
401   { ERF_TYPE_COLOR_HDLC_POS     ,"COLOR_HDLC_POS"},
402   { ERF_TYPE_COLOR_ETH          ,"COLOR_ETH"},
403   { ERF_TYPE_MC_AAL2            ,"MC_AAL2 "},
404   { ERF_TYPE_IP_COUNTER         ,"IP_COUNTER"},
405   { ERF_TYPE_TCP_FLOW_COUNTER   ,"TCP_FLOW_COUNTER"},
406   { ERF_TYPE_DSM_COLOR_HDLC_POS ,"DSM_COLOR_HDLC_POS"},
407   { ERF_TYPE_DSM_COLOR_ETH      ,"DSM_COLOR_ETH "},
408   { ERF_TYPE_COLOR_MC_HDLC_POS  ,"COLOR_MC_HDLC_POS"},
409   { ERF_TYPE_AAL2               ,"AAL2"},
410   { ERF_TYPE_PAD                ,"PAD"},
411   { ERF_TYPE_INFINIBAND         , "INFINIBAND"},
412   { ERF_TYPE_IPV4               , "IPV4"},
413   { ERF_TYPE_IPV6               , "IPV6"},
414   { ERF_TYPE_RAW_LINK           , "RAW_LINK"},
415   { ERF_TYPE_INFINIBAND_LINK    , "INFINIBAND_LINK"},
416   { ERF_TYPE_META               , "META"},
417   {0, NULL}
418 };
419
420 /* Extended headers type defines */
421 static const value_string ehdr_type_vals[] = {
422   { ERF_EXT_HDR_TYPE_CLASSIFICATION , "Classification"},
423   { ERF_EXT_HDR_TYPE_INTERCEPTID    , "InterceptID"},
424   { ERF_EXT_HDR_TYPE_RAW_LINK       , "Raw Link"},
425   { ERF_EXT_HDR_TYPE_BFS            , "BFS Filter/Hash"},
426   { ERF_EXT_HDR_TYPE_CHANNELISED    , "Channelised"},
427   { ERF_EXT_HDR_TYPE_SIGNATURE      , "Signature"},
428   { ERF_EXT_HDR_TYPE_FLOW_ID        , "Flow ID"},
429   { ERF_EXT_HDR_TYPE_HOST_ID        , "Host ID"},
430   { 0, NULL }
431 };
432
433
434 static const value_string raw_link_types[] = {
435   { 0x00, "raw SONET"},
436   { 0x01, "raw SDH"},
437   { 0x02, "SONET spe"},
438   { 0x03, "SDH spe"},
439   { 0x04, "ds3"},
440   { 0x05, "SONET spe w/o POH"},
441   { 0x06, "SDH spe w/o POH"},
442   { 0x07, "SONET line mode 2"},
443   { 0x08, "SHD line mode 2"},
444   { 0x09, "raw bit-level"},
445   { 0x0A, "raw 10Gbe 66b"},
446   { 0, NULL },
447 };
448
449 static const value_string raw_link_rates[] = {
450   { 0x00, "reserved"},
451   { 0x01, "oc3/stm1"},
452   { 0x02, "oc12/stm4"},
453   { 0x03, "oc48/stm16"},
454   { 0x04, "oc192/stm64"},
455   { 0, NULL },
456 };
457
458 static const value_string channelised_assoc_virt_container_size[] = {
459   { 0x00, "unused field"},
460   { 0x01, "VC-3 / STS-1"},
461   { 0x02, "VC-4 / STS-3"},
462   { 0x03, "VC-4-4c / STS-12"},
463   { 0x04, "VC-4-16c / STS-48"},
464   { 0x05, "VC-4-64c / STS-192"},
465   { 0, NULL }
466 };
467
468 static const value_string channelised_rate[] = {
469   { 0x00, "Reserved"},
470   { 0x01, "STM-0 / STS-1"},
471   { 0x02, "STM-1 / STS-3"},
472   { 0x03, "STM-4 / STS-12"},
473   { 0x04, "STM-16 / STS-48"},
474   { 0x05, "STM-64 / STS-192"},
475   { 0, NULL}
476 };
477
478 static const value_string channelised_type[] = {
479   { 0x00, "SOH / TOH"},
480   { 0x01, "POH"},
481   { 0x02, "Container"},
482   { 0x03, "POS Packet"},
483   { 0x04, "ATM Cell"},
484   { 0x05, "Positive justification bytes"},
485   { 0x06, "Raw demultiplexed channel"},
486   { 0, NULL}
487 };
488
489 static const value_string erf_hash_type[] = {
490   { 0x00, "Not set"},
491   { 0x01, "Non-IP (Src/Dst MACs, EtherType)"},
492   { 0x02, "2-tuple (Src/Dst IP Addresses)"},
493   { 0x03, "3-tuple (Src/Dst IP Addresses, IP Protocol)"},
494   { 0x04, "4-tuple (Src/Dst IP Addresses, IP Protocol, Interface ID)"},
495   { 0x05, "5-tuple (Src/Dst IP Addresses, IP Protocol, Src/Dst L4 Ports)"},
496   { 0x06, "6-tuple (Src/Dst IP Addresses, IP Protocol, Src/Dst L4 Ports, Interface ID)"},
497   { 0, NULL}
498 };
499
500 static const value_string erf_stack_type[] = {
501   { 0x00, "Not set"},
502   { 0x01, "Non-IP"},
503   { 0x02, "No VLAN, IPv4"},
504   { 0x03, "No VLAN, IPv6"},
505   { 0x04, "One VLAN, IPv4"},
506   { 0x05, "One VLAN, IPv6"},
507   { 0x06, "Two VLANs, IPv4"},
508   { 0x07, "Two VLANs, IPv6"},
509   { 0, NULL}
510 };
511 static const value_string erf_port_type[] = {
512   { 0x00, "Reserved"},
513   { 0x01, "Capture Port"},
514   { 0x02, "Timing Port"},
515   { 0, NULL}
516 };
517
518 /* Used as templates for ERF_META_TAG_tunneling_mode */
519 static const header_field_info erf_tunneling_modes[] = {
520   { "IP-in-IP", "ip_in_ip", FT_UINT32, BASE_DEC, NULL, 0x1, NULL, HFILL },
521   /* 0x02 is currently unused and reserved */
522   { "VXLAN", "vxlan", FT_UINT32, BASE_DEC, NULL, 0x4, NULL, HFILL },
523   { "GRE", "gre", FT_UINT32, BASE_DEC, NULL, 0x8, NULL, HFILL },
524   { "GTP", "gtp", FT_UINT32, BASE_DEC, NULL, 0x10, NULL, HFILL },
525   { "MPLS over VLAN", "mpls_vlan", FT_UINT32, BASE_DEC, NULL, 0x20, NULL, HFILL }
526 };
527 /* XXX: Must be at least array_length(erf_tunneling_modes). */
528 #define ERF_HF_VALUES_PER_TAG 8
529
530 typedef struct {
531   guint16 code;
532   header_field_info hfinfo;
533 } erf_meta_hf_template_t;
534
535 typedef struct {
536   gint ett_value;
537   /*
538    * XXX: Must be at least array_length(erf_tunneling_modes). Should change to
539    * dynamic (possibly using new proto tree API) if many more fields defined.
540    * Either that or add a value-string-like automatic bitmask flags proto_item.
541    */
542   int hf_values[ERF_HF_VALUES_PER_TAG];
543 } erf_meta_tag_info_ex_t;
544
545 typedef struct {
546   guint16 code;
547   guint16 section;
548   const erf_meta_hf_template_t* tag_template;
549
550   gint ett;
551   int hf_value;
552   erf_meta_tag_info_ex_t *extra;
553   /* TODO: could add a type_value and callback here for greater flexibility */
554 } erf_meta_tag_info_t;
555
556 typedef struct {
557   wmem_map_t* tag_table;
558   wmem_array_t* hfri;
559   wmem_array_t* ett;
560   wmem_array_t* vs_list;
561   wmem_array_t* vs_abbrev_list;
562   erf_meta_tag_info_t* unknown_section_info;
563 } erf_meta_index_t;
564
565 typedef struct {
566   wmem_map_t* source_map;
567   guint64 implicit_host_id;
568 } erf_state_t;
569
570 typedef struct {
571   wmem_tree_t* meta_tree;
572   wmem_list_t* meta_list;
573 } erf_source_info_t;
574
575 #define ERF_SOURCE_KEY(host_id, source_id) (((guint64) host_id << 16) | source_id)
576 #define ERF_TAG_INFO_KEY(tag_info) (((guint32) (tag_info)->section << 16) | (tag_info)->code)
577
578 static erf_meta_index_t erf_meta_index;
579 static erf_state_t erf_state;
580
581 /*
582  * XXX: These header_field_info are used as templates for dynamically building
583  * per-section fields for each tag, as well as appropiate value_string arrays.
584  * We abuse the abbrev field to store the short name of the tags.
585  */
586 static const erf_meta_hf_template_t erf_meta_tags[] = {
587   { ERF_META_TAG_padding,           { "Padding",                            "padding",           FT_NONE,          BASE_NONE,         NULL, 0x0, NULL, HFILL } },
588   { ERF_META_TAG_comment,           { "Comment",                            "comment",           FT_STRING,        BASE_NONE,         NULL, 0x0, NULL, HFILL } },
589   { ERF_META_TAG_gen_time,          { "Metadata Generation Time",           "gen_time",          FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0x0, NULL, HFILL } },
590   { ERF_META_TAG_parent_section,    { "Parent Section",                     "parent_section",    FT_BYTES,         BASE_NONE,         NULL, 0x0, NULL, HFILL } },
591   { ERF_META_TAG_reset,             { "Metadata Reset",                     "reset",             FT_BYTES,         BASE_NONE,         NULL, 0x0, NULL, HFILL } },
592   { ERF_META_TAG_event_time,        { "Event Time",                         "event_time",        FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0x0, NULL, HFILL } },
593   { ERF_META_TAG_host_id,           { "Host ID",                            "host_id",           FT_UINT64,        BASE_HEX,          NULL, 0x0, NULL, HFILL } },
594   { ERF_META_TAG_fcs_len,           { "FCS Length (bits)",                  "fcs_len",           FT_UINT32,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
595   { ERF_META_TAG_mask_ipv4,         { "Subnet Mask (IPv4)",                 "mask_ipv4",         FT_IPv4,          BASE_NETMASK,      NULL, 0x0, NULL, HFILL } },
596   { ERF_META_TAG_mask_cidr,         { "Subnet Mask (CIDR)",                 "mask_cidr",         FT_UINT32,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
597
598   { ERF_META_TAG_org_name,          { "Organisation",                       "org_name",          FT_STRING,        BASE_NONE,         NULL, 0x0, NULL, HFILL } },
599   { ERF_META_TAG_name,              { "Name",                               "name",              FT_STRING,        BASE_NONE,         NULL, 0x0, NULL, HFILL } },
600   { ERF_META_TAG_descr,             { "Description",                        "descr",             FT_STRING,        BASE_NONE,         NULL, 0x0, NULL, HFILL } },
601   { ERF_META_TAG_config,            { "Configuration",                      "config",            FT_STRING,        BASE_NONE,         NULL, 0x0, NULL, HFILL } },
602   { ERF_META_TAG_datapipe,          { "Datapipe Name",                      "datapipe",          FT_STRING,        BASE_NONE,         NULL, 0x0, NULL, HFILL } },
603   { ERF_META_TAG_app_name,          { "Application Name",                   "app_name",          FT_STRING,        BASE_NONE,         NULL, 0x0, NULL, HFILL } },
604   { ERF_META_TAG_os,                { "Operating System",                   "os",                FT_STRING,        BASE_NONE,         NULL, 0x0, NULL, HFILL } },
605   { ERF_META_TAG_hostname,          { "Hostname",                           "hostname",          FT_STRING,        BASE_NONE,         NULL, 0x0, NULL, HFILL } },
606   { ERF_META_TAG_user,              { "User",                               "user",              FT_STRING,        BASE_NONE,         NULL, 0x0, NULL, HFILL } },
607   { ERF_META_TAG_model,             { "Model",                              "model",             FT_STRING,        BASE_NONE,         NULL, 0x0, NULL, HFILL } },
608   { ERF_META_TAG_fw_version,        { "Firmware Version",                   "fw_version",        FT_STRING,        BASE_NONE,         NULL, 0x0, NULL, HFILL } },
609   { ERF_META_TAG_serial_no,         { "Serial Number",                      "serial_no",         FT_STRING,        BASE_NONE,         NULL, 0x0, NULL, HFILL } },
610   { ERF_META_TAG_ts_offset,         { "Timestamp Offset",                   "ts_offset",         FT_RELATIVE_TIME, BASE_NONE,         NULL, 0x0, NULL, HFILL } },
611   { ERF_META_TAG_ts_clock_freq,     { "Timestamp Clock Frequency (Hz)",     "ts_clock_freq",     FT_UINT32,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
612   { ERF_META_TAG_tzone,             { "Timezone Offset",                    "tzone",             FT_INT32,         BASE_DEC,          NULL, 0x0, NULL, HFILL } },
613   { ERF_META_TAG_tzone_name,        { "Timezone Name",                      "tzone_name",        FT_STRING,        BASE_NONE,         NULL, 0x0, NULL, HFILL } },
614   { ERF_META_TAG_loc_lat,           { "Location Latitude",                  "loc_lat",           FT_INT32,         BASE_DEC,          NULL, 0x0, NULL, HFILL } },
615   { ERF_META_TAG_loc_long,          { "Location Longitude",                 "loc_long",          FT_INT32,         BASE_DEC,          NULL, 0x0, NULL, HFILL } },
616   { ERF_META_TAG_snaplen,           { "Snap Length",                        "snaplen",           FT_UINT32,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
617   { ERF_META_TAG_card_num,          { "Card Number",                        "card_num",          FT_UINT32,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
618   { ERF_META_TAG_module_num,        { "Module Number",                      "module_num",        FT_UINT32,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
619   { ERF_META_TAG_access_num,        { "Access Number",                      "access_num",        FT_UINT32,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
620   { ERF_META_TAG_stream_num,        { "Stream Number",                      "stream_num",        FT_UINT32,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
621   { ERF_META_TAG_loc_name,          { "Location Name",                      "loc_name",          FT_STRING,        BASE_NONE,         NULL, 0x0, NULL, HFILL } },
622   { ERF_META_TAG_parent_file,       { "Parent Filename",                    "parent_file",       FT_STRING,        BASE_NONE,         NULL, 0x0, NULL, HFILL } },
623   { ERF_META_TAG_filter,            { "Filter",                             "filter",            FT_STRING,        BASE_NONE,         NULL, 0x0, NULL, HFILL } },
624   { ERF_META_TAG_flow_hash_mode,    { "Flow Hash Mode",                     "flow_hash_mode",    FT_UINT32,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
625   { ERF_META_TAG_tunneling_mode,    { "Tunneling Mode",                     "tunneling_mode",    FT_UINT32,        BASE_HEX,          NULL, 0x0, NULL, HFILL } },
626   { ERF_META_TAG_npb_format,        { "NPB Format",                         "npb_format",        FT_BYTES,         BASE_NONE,         NULL, 0x0, NULL, HFILL } },
627   { ERF_META_TAG_mem,               { "Memory",                             "mem",               FT_UINT64,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
628   { ERF_META_TAG_datamine_id,       { "Datamine ID",                        "datamine_id",       FT_STRING,        BASE_NONE,         NULL, 0x0, NULL, HFILL } },
629   { ERF_META_TAG_rotfile_id,        { "Rotfile ID",                         "rotfile_id",        FT_STRING,        BASE_NONE,         NULL, 0x0, NULL, HFILL } },
630   { ERF_META_TAG_rotfile_name,      { "Rotfile Name",                       "rotfile_name",      FT_STRING,        BASE_NONE,         NULL, 0x0, NULL, HFILL } },
631   { ERF_META_TAG_dev_name,          { "Device Name",                        "dev_name",          FT_STRING,        BASE_NONE,         NULL, 0x0, NULL, HFILL } },
632   { ERF_META_TAG_dev_path,          { "Device Canonical Path",              "dev_path",          FT_STRING,        BASE_NONE,         NULL, 0x0, NULL, HFILL } },
633   { ERF_META_TAG_loc_descr,         { "Location Description",               "loc_descr",         FT_STRING,        BASE_NONE,         NULL, 0x0, NULL, HFILL } },
634   { ERF_META_TAG_app_version,       { "Application Version",                "app_version",       FT_STRING,        BASE_NONE,         NULL, 0x0, NULL, HFILL } },
635   { ERF_META_TAG_cpu_affinity,      { "CPU Affinity Mask",                  "cpu_affinity",      FT_BYTES,         BASE_NONE,         NULL, 0x0, NULL, HFILL } },
636   { ERF_META_TAG_cpu,               { "CPU Model",                          "cpu",               FT_STRING,        BASE_NONE,         NULL, 0x0, NULL, HFILL } },
637   { ERF_META_TAG_cpu_phys_cores,    { "CPU Physical Cores",                 "cpu_phys_cores",    FT_UINT32,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
638   { ERF_META_TAG_cpu_numa_nodes,    { "CPU NUMA Nodes",                     "cpu_numa_nodes",    FT_UINT32,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
639   { ERF_META_TAG_dag_attribute,     { "DAG Attribute",                      "dag_attribute",     FT_STRING,        BASE_NONE,         NULL, 0x0, NULL, HFILL } },
640   { ERF_META_TAG_dag_version,       { "DAG Software Version",               "dag_attribute",     FT_STRING,        BASE_NONE,         NULL, 0x0, NULL, HFILL } },
641
642   { ERF_META_TAG_if_num,            { "Interface Number",                   "if_num",            FT_UINT32,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
643   { ERF_META_TAG_if_vc,             { "Interface Virtual Circuit",          "if_vc",             FT_UINT32,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
644   { ERF_META_TAG_if_speed,          { "Interface Line Rate",                "if_speed",          FT_UINT64,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
645   { ERF_META_TAG_if_ipv4,           { "Interface IPv4 address",             "if_ipv4",           FT_IPv4,          BASE_NONE,         NULL, 0x0, NULL, HFILL } },
646   { ERF_META_TAG_if_ipv6,           { "Interface IPv6 address",             "if_ipv6",           FT_IPv6,          BASE_NONE,         NULL, 0x0, NULL, HFILL } },
647   { ERF_META_TAG_if_mac,            { "Interface MAC address",              "if_mac",            FT_ETHER,         BASE_NONE,         NULL, 0x0, NULL, HFILL } },
648   { ERF_META_TAG_if_eui,            { "Interface EUI-64 address",           "if_eui",            FT_EUI64,         BASE_NONE,         NULL, 0x0, NULL, HFILL } },
649   { ERF_META_TAG_if_ib_gid,         { "Interface InfiniBand GID",           "if_ib_gid",         FT_IPv6,          BASE_NONE,         NULL, 0x0, NULL, HFILL } },
650   { ERF_META_TAG_if_ib_lid,         { "Interface InfiniBand LID",           "if_ib_lid",         FT_UINT16,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
651   { ERF_META_TAG_if_wwn,            { "Interface WWN",                      "if_wwn",            FT_FCWWN,         BASE_NONE,         NULL, 0x0, NULL, HFILL } },
652   { ERF_META_TAG_if_fc_id,          { "Interface FCID address",             "if_fc_id",          FT_BYTES,         SEP_DOT,           NULL, 0x0, NULL, HFILL } },
653   { ERF_META_TAG_if_tx_speed,       { "Interface TX Line Rate",             "if_tx_speed",       FT_UINT64,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
654   { ERF_META_TAG_if_erf_type,       { "Interface ERF type",                 "if_erf_type",       FT_UINT32,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
655   { ERF_META_TAG_if_link_type,      { "Interface link type",                "if_link_type",      FT_UINT32,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
656   { ERF_META_TAG_if_sfp_type,       { "Interface Transceiver type",         "if_sfp_type",       FT_STRING,        BASE_NONE,         NULL, 0x0, NULL, HFILL } },
657   { ERF_META_TAG_if_rx_power,       { "Interface RX Optical Power",         "if_rx_power",       FT_INT32,         BASE_DEC,          NULL, 0x0, NULL, HFILL } },
658   { ERF_META_TAG_if_tx_power,       { "Interface TX Optical Power",         "if_tx_power",       FT_INT32,         BASE_DEC,          NULL, 0x0, NULL, HFILL } },
659   { ERF_META_TAG_if_link_status,    { "Interface Link Status",              "if_link_status",    FT_UINT32,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
660   { ERF_META_TAG_if_phy_mode,       { "Interface Endace PHY Mode",          "if_phy_mode",       FT_STRING,        BASE_NONE,         NULL, 0x0, NULL, HFILL } },
661   { ERF_META_TAG_if_port_type,      { "Interface Port Type",                "if_port_type",      FT_UINT32,        BASE_DEC,          VALS(erf_port_type), 0x0, NULL, HFILL } },
662
663   { ERF_META_TAG_src_ipv4,          { "Source IPv4 address",                "src_ipv4",          FT_IPv4,          BASE_NONE,         NULL, 0x0, NULL, HFILL } },
664   { ERF_META_TAG_dest_ipv4,         { "Destination IPv4 address",           "dest_ipv4",         FT_IPv4,          BASE_NONE,         NULL, 0x0, NULL, HFILL } },
665   { ERF_META_TAG_src_ipv6,          { "Source IPv6 address",                "src_ipv6",          FT_IPv6,          BASE_NONE,         NULL, 0x0, NULL, HFILL } },
666   { ERF_META_TAG_dest_ipv6,         { "Destination IPv6 address",           "dest_ipv6",         FT_IPv6,          BASE_NONE,         NULL, 0x0, NULL, HFILL } },
667   { ERF_META_TAG_src_mac,           { "Source MAC address",                 "src_mac",           FT_ETHER,         BASE_NONE,         NULL, 0x0, NULL, HFILL } },
668   { ERF_META_TAG_dest_mac,          { "Destination MAC address",            "dest_mac",          FT_ETHER,         BASE_NONE,         NULL, 0x0, NULL, HFILL } },
669   { ERF_META_TAG_src_eui,           { "Source EUI-64 address",              "src_eui",           FT_EUI64,         BASE_NONE,         NULL, 0x0, NULL, HFILL } },
670   { ERF_META_TAG_dest_eui,          { "Destination EUI-64 address",         "dest_eui",          FT_EUI64,         BASE_NONE,         NULL, 0x0, NULL, HFILL } },
671   { ERF_META_TAG_src_ib_gid,        { "Source InfiniBand GID address",      "src_ib_gid",        FT_IPv6,          BASE_NONE,         NULL, 0x0, NULL, HFILL } },
672   { ERF_META_TAG_dest_ib_gid,       { "Destination InfiniBand GID address", "dest_ib_gid",       FT_IPv6,          BASE_NONE,         NULL, 0x0, NULL, HFILL } },
673   { ERF_META_TAG_src_ib_lid,        { "Source InfiniBand LID address",      "src_ib_lid",        FT_UINT16,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
674   { ERF_META_TAG_dest_ib_lid,       { "Destination InfiniBand LID address", "dest_ib_lid",       FT_UINT16,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
675   { ERF_META_TAG_src_wwn,           { "Source WWN address",                 "src_wwn",           FT_FCWWN,         BASE_NONE,         NULL, 0x0, NULL, HFILL } },
676   { ERF_META_TAG_dest_wwn,          { "Destination WWN address",            "dest_wwn",          FT_FCWWN,         BASE_NONE,         NULL, 0x0, NULL, HFILL } },
677   { ERF_META_TAG_src_fc_id,         { "Source FCID address",                "src_fc_id",         FT_BYTES,         SEP_DOT,           NULL, 0x0, NULL, HFILL } },
678   { ERF_META_TAG_dest_fc_id,        { "Destination FCID address",           "dest_fc_id",        FT_BYTES,         SEP_DOT,           NULL, 0x0, NULL, HFILL } },
679   { ERF_META_TAG_src_port,          { "Source Port",                        "src_port",          FT_UINT32,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
680   { ERF_META_TAG_dest_port,         { "Destination Port",                   "dest_port",         FT_UINT32,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
681   { ERF_META_TAG_ip_proto,          { "IP Protocol",                        "ip_proto",          FT_UINT32,        BASE_DEC|BASE_EXT_STRING, &ipproto_val_ext, 0x0, NULL, HFILL } },
682   { ERF_META_TAG_flow_hash,         { "Flow Hash",                          "flow_hash",         FT_UINT32,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
683   { ERF_META_TAG_filter_match,      { "Filter Match",                       "filter_match",      FT_STRING,        BASE_NONE,         NULL, 0x0, NULL, HFILL } },
684   { ERF_META_TAG_filter_match_name, { "Filter Match Name",                  "filter_match_name", FT_STRING,        BASE_NONE,         NULL, 0x0, NULL, HFILL } },
685   { ERF_META_TAG_error_flags,       { "Error Flags",                        "error_flags",       FT_BYTES,         BASE_NONE,         NULL, 0x0, NULL, HFILL } },
686
687   { ERF_META_TAG_start_time,        { "Start Time",                         "start_time",        FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0x0, NULL, HFILL } },
688   { ERF_META_TAG_end_time,          { "End Time",                           "end_time",          FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0x0, NULL, HFILL } },
689   { ERF_META_TAG_stat_if_drop,      { "Interface Drop",                     "stat_if_drop",      FT_UINT64,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
690   { ERF_META_TAG_stat_frames,       { "Packets Received",                   "stat_frames",       FT_UINT64,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
691   { ERF_META_TAG_stat_bytes,        { "Bytes Received",                     "stat_bytes",        FT_UINT64,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
692   { ERF_META_TAG_stat_cap,          { "Packets Captured",                   "stat_cap",          FT_UINT64,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
693   { ERF_META_TAG_stat_cap_bytes,    { "Bytes Captured",                     "stat_cap_bytes",    FT_UINT64,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
694   { ERF_META_TAG_stat_os_drop,      { "OS Drop",                            "stat_os_drop",      FT_UINT64,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
695   { ERF_META_TAG_stat_ds_lctr,      { "Internal Error Drop",                "stat_ds_lctr",      FT_UINT64,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
696   { ERF_META_TAG_stat_filter_match, { "Filter Match",                       "stat_filter_match", FT_UINT64,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
697   { ERF_META_TAG_stat_filter_drop,  { "Filter Drop",                        "stat_filter_drop",  FT_UINT64,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
698   { ERF_META_TAG_stat_too_short,    { "Packets Too Short",                  "stat_too_short",    FT_UINT64,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
699   { ERF_META_TAG_stat_too_long,     { "Packets Too Long",                   "stat_too_long",     FT_UINT64,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
700   { ERF_META_TAG_stat_rx_error,     { "Packets RX Error",                   "stat_rx_error",     FT_UINT64,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
701   { ERF_META_TAG_stat_fcs_error,    { "Packets FCS Error",                  "stat_fcs_error",    FT_UINT64,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
702   { ERF_META_TAG_stat_aborted,      { "Packets Aborted",                    "stat_aborted",      FT_UINT64,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
703   { ERF_META_TAG_stat_proto_error,  { "Packets Protocol Error",             "stat_proto_error",  FT_UINT64,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
704   { ERF_META_TAG_stat_b1_error,     { "SDH B1 Errors",                      "stat_b1_error",     FT_UINT64,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
705   { ERF_META_TAG_stat_b2_error,     { "SDH B2 Errors",                      "stat_b2_error",     FT_UINT64,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
706   { ERF_META_TAG_stat_b3_error,     { "SDH B3 Errors",                      "stat_b3_error",     FT_UINT64,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
707   { ERF_META_TAG_stat_rei_error,    { "SDH REI Errors",                     "stat_rei_error",    FT_UINT64,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
708   { ERF_META_TAG_stat_drop,         { "Packets Dropped",                    "stat_drop",         FT_UINT64,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
709   { ERF_META_TAG_stat_buf_drop,     { "Buffer Drop",                        "stat_buf_drop",     FT_UINT64,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
710   { ERF_META_TAG_stream_drop,       { "Stream Drop",                        "stream_drop",       FT_UINT32,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
711   { ERF_META_TAG_stream_buf_drop,   { "Stream Buffer Drop",                 "stream_buf_drop",   FT_UINT32,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
712
713   { ERF_META_TAG_ns_host_ipv4,      { "IPv4 Name",                          "ns_host_ipv4",      FT_IPv4,          BASE_NONE,         NULL, 0x0, NULL, HFILL } },
714   { ERF_META_TAG_ns_host_ipv6,      { "IPv6 Name",                          "ns_host_ipv6",      FT_IPv6,          BASE_NONE,         NULL, 0x0, NULL, HFILL } },
715   { ERF_META_TAG_ns_host_mac,       { "MAC Name",                           "ns_host_mac",       FT_ETHER,         BASE_NONE,         NULL, 0x0, NULL, HFILL } },
716   { ERF_META_TAG_ns_host_eui,       { "EUI Name",                           "ns_host_eui",       FT_EUI64,         BASE_NONE,         NULL, 0x0, NULL, HFILL } },
717   { ERF_META_TAG_ns_host_ib_gid,    { "InfiniBand GID Name",                "ns_host_ib_gid",    FT_IPv6,          BASE_NONE,         NULL, 0x0, NULL, HFILL } },
718   { ERF_META_TAG_ns_host_ib_lid,    { "InfiniBand LID Name",                "ns_host_ib_lid",    FT_UINT16,        BASE_DEC,          NULL, 0x0, NULL, HFILL } },
719   { ERF_META_TAG_ns_host_wwn,       { "WWN Name",                           "ns_host_wwn",       FT_FCWWN,         BASE_NONE,         NULL, 0x0, NULL, HFILL } },
720   { ERF_META_TAG_ns_host_fc_id,     { "FCID Name",                          "ns_host_fc_id",     FT_BYTES,         SEP_DOT,           NULL, 0x0, NULL, HFILL } },
721   { ERF_META_TAG_ns_dns_ipv4,       { "Nameserver IPv4 address",            "ns_dns_ipv4",       FT_IPv4,          BASE_NONE,         NULL, 0x0, NULL, HFILL } },
722   { ERF_META_TAG_ns_dns_ipv6,       { "Nameserver IPv6 address",            "ns_dns_ipv6",       FT_IPv6,          BASE_NONE,         NULL, 0x0, NULL, HFILL } },
723
724   { ERF_META_TAG_exthdr,            { "ERF Extension Header",               "exthdr",            FT_BYTES,         BASE_NONE,         NULL, 0x0, NULL, HFILL } },
725   { ERF_META_TAG_pcap_ng_block,     { "PCAP-NG Block",                      "pcap_ng_block",     FT_BYTES,         BASE_NONE,         NULL, 0x0, NULL, HFILL } },
726   { ERF_META_TAG_asn1,              { "ASN.1",                              "asn1",              FT_BYTES,         BASE_NONE,         NULL, 0x0, NULL, HFILL } }
727 };
728
729 /* Sections are also tags, but enumerate them seperately to make logic simpler */
730 static const erf_meta_hf_template_t erf_meta_sections[] = {
731   /*
732    * Some tags (such as generation time) can appear before the first section,
733    * we group these together into a fake section for consistency.
734    */
735   { ERF_META_SECTION_NONE,          { "No Section",                         "section_none",      FT_NONE,          BASE_NONE,         NULL, 0x0, NULL, HFILL } },
736   { ERF_META_SECTION_UNKNOWN,       { "Unknown Section",                    "section_unknown",   FT_NONE,          BASE_NONE,         NULL, 0x0, NULL, HFILL } },
737
738   { ERF_META_SECTION_CAPTURE,       { "Capture Section",                    "section_capture",   FT_NONE,          BASE_NONE,         NULL, 0x0, NULL, HFILL } },
739   { ERF_META_SECTION_HOST,          { "Host Section",                       "section_host",      FT_NONE,          BASE_NONE,         NULL, 0x0, NULL, HFILL } },
740   { ERF_META_SECTION_MODULE,        { "Module Section",                     "section_module",    FT_NONE,          BASE_NONE,         NULL, 0x0, NULL, HFILL } },
741   { ERF_META_SECTION_INTERFACE,     { "Interface Section",                  "section_interface", FT_NONE,          BASE_NONE,         NULL, 0x0, NULL, HFILL } },
742   { ERF_META_SECTION_FLOW,          { "Flow Section",                       "section_flow",      FT_NONE,          BASE_NONE,         NULL, 0x0, NULL, HFILL } },
743   { ERF_META_SECTION_STATS,         { "Statistics Section",                 "section_stats",     FT_NONE,          BASE_NONE,         NULL, 0x0, NULL, HFILL } },
744   { ERF_META_SECTION_INFO,          { "Information Section",                "section_info",      FT_NONE,          BASE_NONE,         NULL, 0x0, NULL, HFILL } },
745   { ERF_META_SECTION_CONTEXT,       { "Context Section",                    "section_context",   FT_NONE,          BASE_NONE,         NULL, 0x0, NULL, HFILL } },
746   { ERF_META_SECTION_STREAM,        { "Stream Section",                     "section_stream",    FT_NONE,          BASE_NONE,         NULL, 0x0, NULL, HFILL } },
747   { ERF_META_SECTION_TRANSFORM,     { "Transform Section",                  "section_transform", FT_NONE,          BASE_NONE,         NULL, 0x0, NULL, HFILL } },
748   { ERF_META_SECTION_DNS,           { "DNS Section",                        "section_dns",       FT_NONE,          BASE_NONE,         NULL, 0x0, NULL, HFILL } },
749   { ERF_META_SECTION_SOURCE,        { "Source Section",                     "section_source",    FT_NONE,          BASE_NONE,         NULL, 0x0, NULL, HFILL } }
750 };
751
752 static erf_meta_tag_info_ex_t* erf_meta_tag_info_ex_new(wmem_allocator_t *allocator) {
753   gsize i = 0;
754   erf_meta_tag_info_ex_t *extra = wmem_new0(allocator, erf_meta_tag_info_ex_t);
755
756   extra->ett_value = -1;
757   for (i = 0; i < array_length(extra->hf_values); i++) {
758     extra->hf_values[i] = -1;
759   }
760
761   return extra;
762 }
763
764 static erf_meta_tag_info_t*
765 init_section_fields(wmem_array_t *hfri_table, wmem_array_t *ett_table, const erf_meta_hf_template_t *section)
766 {
767   erf_meta_tag_info_t *section_info;
768   gint                *ett_tmp; /* wmem_array_append needs actual memory to copy from */
769   hf_register_info     hfri_tmp[] = {
770     { NULL, { "Section ID", NULL, FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, /* Section ID */
771     { NULL, { "Section Length", NULL, FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},  /* Section Length */
772     { NULL, { "Reserved", NULL, FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }} /* Reserved extra bytes */
773   };
774
775   section_info = wmem_new0(wmem_epan_scope(), erf_meta_tag_info_t);
776   section_info->code = section->code;
777   section_info->section = section->code; /* Needed for lookup commonality */
778   section_info->ett = -1;
779   section_info->hf_value = -1;
780   section_info->tag_template = section;
781   section_info->extra = erf_meta_tag_info_ex_new(wmem_epan_scope());
782
783   hfri_tmp[0].hfinfo.abbrev = wmem_strconcat(wmem_epan_scope(), "erf.meta.", section->hfinfo.abbrev, ".section_id", NULL);
784   hfri_tmp[0].p_id = &section_info->hf_value;
785   hfri_tmp[1].hfinfo.abbrev = wmem_strconcat(wmem_epan_scope(), "erf.meta.", section->hfinfo.abbrev, ".section_len", NULL);
786   hfri_tmp[1].p_id = &section_info->extra->hf_values[0];
787   hfri_tmp[2].hfinfo.abbrev = wmem_strconcat(wmem_epan_scope(), "erf.meta.", section->hfinfo.abbrev, ".section_hdr_rsvd", NULL);
788   hfri_tmp[2].p_id = &section_info->extra->hf_values[1];
789
790   /* Add hf_register_info, ett entries */
791   wmem_array_append(hfri_table, hfri_tmp, array_length(hfri_tmp));
792   ett_tmp = &section_info->ett;
793   wmem_array_append(ett_table, &ett_tmp, 1);
794   ett_tmp = &section_info->extra->ett_value;
795   wmem_array_append(ett_table, &ett_tmp, 1);
796
797   return section_info;
798 }
799
800 static erf_meta_tag_info_t*
801 init_tag_fields(wmem_array_t *hfri_table, wmem_array_t *ett_table, const erf_meta_hf_template_t *section, const erf_meta_hf_template_t *tag)
802 {
803   erf_meta_tag_info_t *tag_info;
804   unsigned int         i = 0;
805   gint                *ett_tmp; /* wmem_array_append needs actual memory to copy from */
806   hf_register_info     hfri_tmp[] = {
807     { NULL, { NULL, NULL, FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, /* Value, will be filled from template */
808     { NULL, { NULL, NULL, FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}  /* Second value, if any */
809   };
810   guint                hfri_len = 0;
811
812   tag_info = wmem_new0(wmem_epan_scope(), erf_meta_tag_info_t);
813   tag_info->code = tag->code;
814   tag_info->section = section->code;
815   tag_info->ett = -1;
816   tag_info->hf_value = -1;
817   tag_info->tag_template = tag;
818   tag_info->extra = NULL;
819
820   switch (tag_info->code) {
821   /* Special case: parent section */
822   case ERF_META_TAG_parent_section:
823     tag_info->extra = erf_meta_tag_info_ex_new(wmem_epan_scope());
824
825     hfri_tmp[0].p_id = &tag_info->hf_value;
826     hfri_tmp[0].hfinfo.name = "Section Type";
827     hfri_tmp[0].hfinfo.abbrev = wmem_strconcat(wmem_epan_scope(), "erf.meta.", section->hfinfo.abbrev, ".", tag->hfinfo.abbrev, ".section_type", NULL);
828     hfri_tmp[0].hfinfo.type = FT_UINT16;
829     hfri_tmp[0].hfinfo.display = BASE_DEC;
830     /* XXX: Cannot set strings here as array may be realloced as more added! */
831     hfri_len++;
832
833     hfri_tmp[1].p_id = &tag_info->extra->hf_values[0];
834     hfri_tmp[1].hfinfo.name = "Section ID";
835     hfri_tmp[1].hfinfo.abbrev = wmem_strconcat(wmem_epan_scope(), "erf.meta.", section->hfinfo.abbrev, ".", tag->hfinfo.abbrev, ".section_id", NULL);
836     hfri_tmp[1].hfinfo.type = FT_UINT16;
837     hfri_tmp[1].hfinfo.display = BASE_DEC;
838     hfri_len++;
839     break;
840
841   /* Special case: Link Status bits */
842   case ERF_META_TAG_if_link_status:
843     tag_info->extra = erf_meta_tag_info_ex_new(wmem_epan_scope());
844
845     hfri_tmp[0].p_id = &tag_info->hf_value;
846     hfri_tmp[0].hfinfo = tag->hfinfo;
847     hfri_tmp[0].hfinfo.abbrev = wmem_strconcat(wmem_epan_scope(), "erf.meta.", section->hfinfo.abbrev, ".", tag->hfinfo.abbrev, NULL);
848     hfri_len++;
849
850     hfri_tmp[1].p_id = &tag_info->extra->hf_values[0];
851     hfri_tmp[1].hfinfo.name = "Link";
852     hfri_tmp[1].hfinfo.abbrev = wmem_strconcat(wmem_epan_scope(), "erf.meta.", section->hfinfo.abbrev, ".", tag->hfinfo.abbrev, ".link", NULL);
853     hfri_tmp[1].hfinfo.type = FT_UINT32;
854     hfri_tmp[1].hfinfo.display = BASE_DEC;
855     hfri_tmp[1].hfinfo.bitmask = 0x00000001;
856     hfri_len++;
857     break;
858
859   /* Special case: Tunneling mode bits */
860   case ERF_META_TAG_tunneling_mode:
861     tag_info->extra = erf_meta_tag_info_ex_new(wmem_epan_scope());
862
863     hfri_tmp[0].p_id = &tag_info->hf_value;
864     hfri_tmp[0].hfinfo = tag->hfinfo;
865     hfri_tmp[0].hfinfo.abbrev = wmem_strconcat(wmem_epan_scope(), "erf.meta.", section->hfinfo.abbrev, ".", tag->hfinfo.abbrev, NULL);
866     hfri_len++;
867
868     /* Borrow hfri_tmp[1], inserting each bitfield value */
869     for (i = 0; i < array_length(erf_tunneling_modes); i++) {
870       hfri_tmp[1].p_id = &tag_info->extra->hf_values[i];
871       hfri_tmp[1].hfinfo = erf_tunneling_modes[i];
872       hfri_tmp[1].hfinfo.abbrev = wmem_strconcat(wmem_epan_scope(), "erf.meta.", section->hfinfo.abbrev, ".", tag->hfinfo.abbrev, ".", erf_tunneling_modes[i].abbrev, NULL);
873       wmem_array_append(hfri_table, &hfri_tmp[1], 1);
874     }
875     break;
876
877   /* Special case: name entry */
878   case ERF_META_TAG_ns_dns_ipv4:
879   case ERF_META_TAG_ns_dns_ipv6:
880   case ERF_META_TAG_ns_host_ipv4:
881   case ERF_META_TAG_ns_host_ipv6:
882   case ERF_META_TAG_ns_host_mac:
883   case ERF_META_TAG_ns_host_eui:
884   case ERF_META_TAG_ns_host_wwn:
885   case ERF_META_TAG_ns_host_ib_gid:
886   case ERF_META_TAG_ns_host_ib_lid:
887   case ERF_META_TAG_ns_host_fc_id:
888     tag_info->extra = erf_meta_tag_info_ex_new(wmem_epan_scope());
889
890     hfri_tmp[0].p_id = &tag_info->hf_value;
891     /* Set type, etc. from template based on address type */
892     hfri_tmp[0].hfinfo = tag->hfinfo;
893     hfri_tmp[0].hfinfo.name = "Address";
894     hfri_tmp[0].hfinfo.abbrev = wmem_strconcat(wmem_epan_scope(), "erf.meta.", section->hfinfo.abbrev, ".", tag->hfinfo.abbrev, ".addr", NULL);
895     hfri_len++;
896
897     hfri_tmp[1].p_id = &tag_info->extra->hf_values[0];
898     hfri_tmp[1].hfinfo.name = "Name";
899     hfri_tmp[1].hfinfo.abbrev = wmem_strconcat(wmem_epan_scope(), "erf.meta.", section->hfinfo.abbrev, ".", tag->hfinfo.abbrev, ".name", NULL);
900     hfri_tmp[1].hfinfo.type = FT_STRING;
901     hfri_tmp[1].hfinfo.display = BASE_NONE;
902     hfri_len++;
903     break;
904
905   /* Usual case: just use template */
906   default:
907     hfri_tmp[0].p_id = &tag_info->hf_value;
908     hfri_tmp[0].hfinfo = tag->hfinfo;
909     hfri_tmp[0].hfinfo.abbrev = wmem_strconcat(wmem_epan_scope(), "erf.meta.", section->hfinfo.abbrev, ".", tag->hfinfo.abbrev, NULL);
910     hfri_len++;
911     break;
912   }
913
914   /* Add hf_register_info, ett entries */
915   wmem_array_append(hfri_table, hfri_tmp, hfri_len);
916   ett_tmp = &tag_info->ett;
917   wmem_array_append(ett_table, &ett_tmp, 1);
918
919   return tag_info;
920 }
921
922 static void
923 init_meta_tags(void)
924 {
925   unsigned int                  i, j    = 0;
926   const erf_meta_hf_template_t *section = NULL;
927   const erf_meta_hf_template_t *tag     = NULL;
928   erf_meta_tag_info_t          *tag_info;
929   value_string                  vs_tmp  = {0, NULL};
930
931   erf_meta_index.tag_table      = wmem_map_new(wmem_epan_scope(), g_direct_hash, g_direct_equal);
932   erf_meta_index.vs_list        = wmem_array_new(wmem_epan_scope(), sizeof(value_string));
933   erf_meta_index.vs_abbrev_list = wmem_array_new(wmem_epan_scope(), sizeof(value_string));
934   erf_meta_index.hfri           = wmem_array_new(wmem_epan_scope(), sizeof(hf_register_info));
935   erf_meta_index.ett            = wmem_array_new(wmem_epan_scope(), sizeof(gint*));
936
937   /* Generate tag fields */
938   for (j = 0; j < array_length(erf_meta_tags); j++) {
939     tag = &erf_meta_tags[j];
940
941     /* Generate copy of the tag for each section */
942     for (i = 0; i < array_length(erf_meta_sections); i++) {
943       section = &erf_meta_sections[i];
944       tag_info = init_tag_fields(erf_meta_index.hfri, erf_meta_index.ett, section, tag);
945       /* Add to hash table */
946       wmem_map_insert(erf_meta_index.tag_table, GUINT_TO_POINTER(ERF_TAG_INFO_KEY(tag_info)), tag_info);
947     }
948
949     /* Add value string entries */
950     vs_tmp.value = tag->code;
951     vs_tmp.strptr = tag->hfinfo.name;
952     wmem_array_append_one(erf_meta_index.vs_list, vs_tmp);
953     vs_tmp.value = tag->code;
954     vs_tmp.strptr = tag->hfinfo.abbrev;
955     wmem_array_append_one(erf_meta_index.vs_abbrev_list, vs_tmp);
956   }
957
958   /* Generate section fields (skipping section_none and parts of section_unknown) */
959   for (i = 1; i < array_length(erf_meta_sections); i++) {
960     section = &erf_meta_sections[i];
961     tag_info = init_section_fields(erf_meta_index.hfri, erf_meta_index.ett, section);
962
963     if (i != 1) { /* don't add value string for unknown section as it doesn't correspond to one section type code */
964       /* Add to hash table */
965       wmem_map_insert(erf_meta_index.tag_table, GUINT_TO_POINTER(ERF_TAG_INFO_KEY(tag_info)), tag_info);
966       /* Add value string entries */
967       vs_tmp.value = section->code;
968       vs_tmp.strptr = section->hfinfo.name;
969       wmem_array_append_one(erf_meta_index.vs_list, vs_tmp);
970       vs_tmp.value = section->code;
971       vs_tmp.strptr = section->hfinfo.abbrev;
972       wmem_array_append_one(erf_meta_index.vs_abbrev_list, vs_tmp);
973     } else {
974       /* Store section_unknown separately to simplify logic later */
975       erf_meta_index.unknown_section_info = tag_info;
976     }
977   }
978
979   /* Terminate value string lists with {0, NULL} */
980   vs_tmp.value = 0;
981   vs_tmp.strptr = NULL;
982   wmem_array_append_one(erf_meta_index.vs_list, vs_tmp);
983   wmem_array_append_one(erf_meta_index.vs_abbrev_list, vs_tmp);
984   /* TODO: try value_string_ext, requires sorting first */
985 }
986
987 static int
988 erf_source_append(guint64 host_id, guint8 source_id, guint32 num)
989 {
990   erf_source_info_t *source_info;
991   guint64            source_key = ERF_SOURCE_KEY(host_id, source_id);
992
993   source_info = (erf_source_info_t*) wmem_map_lookup(erf_state.source_map, &source_key);
994
995   if (!source_info) {
996     guint64 *source_key_ptr = wmem_new(wmem_file_scope(), guint64);
997     *source_key_ptr = source_key;
998
999     source_info = (erf_source_info_t*) wmem_new(wmem_file_scope(), erf_source_info_t);
1000     source_info->meta_tree = wmem_tree_new(wmem_file_scope());
1001     source_info->meta_list = wmem_list_new(wmem_file_scope());
1002
1003     wmem_map_insert(erf_state.source_map, source_key_ptr, source_info);
1004   }
1005
1006   /* Add the frame to the list for that source */
1007   wmem_list_append(source_info->meta_list, GUINT_TO_POINTER(num));
1008   /*
1009    * XXX: This assumes we are inserting fd_num in order, which we are as we use
1010    * PINFO_FD_VISITED in caller.
1011    */
1012   wmem_tree_insert32(source_info->meta_tree, num, wmem_list_tail(source_info->meta_list));
1013
1014   return 0;
1015 }
1016
1017 static guint32
1018 erf_source_find_closest(guint64 host_id, guint8 source_id, guint32 fnum, guint32 *fnum_next_ptr) {
1019   wmem_list_frame_t  *list_frame      = NULL;
1020   wmem_list_frame_t  *list_frame_prev = NULL;
1021   erf_source_info_t  *source_info     = NULL;
1022   guint64             source_key      = ERF_SOURCE_KEY(host_id, source_id);
1023   guint32             fnum_prev       = G_MAXUINT32;
1024   guint32             fnum_next       = G_MAXUINT32;
1025
1026   source_info = (erf_source_info_t*) wmem_map_lookup(erf_state.source_map, &source_key);
1027
1028   if (source_info) {
1029     list_frame = (wmem_list_frame_t*) wmem_tree_lookup32_le(source_info->meta_tree, fnum);
1030
1031     if (list_frame) {
1032       fnum_prev = GPOINTER_TO_UINT(wmem_list_frame_data(list_frame));
1033       /* If looking at a metadata record, get the real previous meta frame */
1034       if (fnum_prev == fnum) {
1035         list_frame_prev = wmem_list_frame_prev(list_frame);
1036         fnum_prev = list_frame_prev ? GPOINTER_TO_UINT(wmem_list_frame_data(list_frame_prev)) : G_MAXUINT32;
1037       }
1038
1039       list_frame = wmem_list_frame_next(list_frame);
1040       fnum_next = list_frame ? GPOINTER_TO_UINT(wmem_list_frame_data(list_frame)) : G_MAXUINT32;
1041     } else {
1042       /*
1043        * XXX: Edge case: still need the first meta record to find the next one at the
1044        * beginning of the file.
1045        */
1046       list_frame = wmem_list_head(source_info->meta_list);
1047       fnum_next = list_frame ? GPOINTER_TO_UINT(wmem_list_frame_data(list_frame)) : G_MAXUINT32;
1048       fnum_prev = G_MAXUINT32;
1049     }
1050   }
1051
1052   if (fnum_next_ptr)
1053     *fnum_next_ptr = fnum_next;
1054
1055   return fnum_prev;
1056 }
1057
1058 /* Copy of atm_guess_traffic_type from atm.c in /wiretap */
1059 static void
1060 erf_atm_guess_lane_type(tvbuff_t *tvb, int offset, guint len,
1061     struct atm_phdr *atm_info)
1062 {
1063   if (len >= 2) {
1064     if (tvb_get_ntohs(tvb, offset) == 0xFF00) {
1065       /*
1066        * Looks like LE Control traffic.
1067        */
1068       atm_info->subtype = TRAF_ST_LANE_LE_CTRL;
1069     } else {
1070       /*
1071        * XXX - Ethernet, or Token Ring?
1072        * Assume Ethernet for now; if we see earlier
1073        * LANE traffic, we may be able to figure out
1074        * the traffic type from that, but there may
1075        * still be situations where the user has to
1076        * tell us.
1077        */
1078       atm_info->subtype = TRAF_ST_LANE_802_3;
1079     }
1080   }
1081 }
1082
1083 static void
1084 erf_atm_guess_traffic_type(tvbuff_t *tvb, int offset, guint len,
1085     struct atm_phdr *atm_info)
1086 {
1087   /*
1088    * Start out assuming nothing other than that it's AAL5.
1089    */
1090   atm_info->aal     = AAL_5;
1091   atm_info->type    = TRAF_UNKNOWN;
1092   atm_info->subtype = TRAF_ST_UNKNOWN;
1093
1094   if (atm_info->vpi == 0) {
1095     /*
1096      * Traffic on some PVCs with a VPI of 0 and certain
1097      * VCIs is of particular types.
1098      */
1099     switch (atm_info->vci) {
1100
1101     case 5:
1102       /*
1103        * Signalling AAL.
1104        */
1105       atm_info->aal = AAL_SIGNALLING;
1106       return;
1107
1108     case 16:
1109       /*
1110        * ILMI.
1111        */
1112       atm_info->type = TRAF_ILMI;
1113       return;
1114     }
1115   }
1116
1117   /*
1118    * OK, we can't tell what it is based on the VPI/VCI; try
1119    * guessing based on the contents, if we have enough data
1120    * to guess.
1121    */
1122
1123   if (len >= 3) {
1124     guint8 mtp3b;
1125     if (tvb_get_ntoh24(tvb, offset) == 0xAAAA03) {
1126       /*
1127        * Looks like a SNAP header; assume it's LLC
1128        * multiplexed RFC 1483 traffic.
1129        */
1130       atm_info->type = TRAF_LLCMX;
1131     } else if ((atm_info->aal5t_len &&
1132                 atm_info->aal5t_len < 16) || len<16) {
1133       /*
1134        * As this cannot be a LANE Ethernet frame (less
1135        * than 2 bytes of LANE header + 14 bytes of
1136        * Ethernet header) we can try it as a SSCOP frame.
1137        */
1138       atm_info->aal = AAL_SIGNALLING;
1139     } else if (((mtp3b = tvb_get_guint8(tvb, offset)) == 0x83) || (mtp3b == 0x81)) {
1140       /*
1141        * MTP3b headers often encapsulate
1142        * a SCCP or MTN in the 3G network.
1143        * This should cause 0x83 or 0x81
1144        * in the first byte.
1145        */
1146       atm_info->aal = AAL_SIGNALLING;
1147     } else {
1148       /*
1149        * Assume it's LANE.
1150        */
1151       atm_info->type = TRAF_LANE;
1152       erf_atm_guess_lane_type(tvb, offset, len, atm_info);
1153     }
1154   } else {
1155     /*
1156      * Not only VCI 5 is used for signaling. It might be
1157      * one of these VCIs.
1158      */
1159     atm_info->aal = AAL_SIGNALLING;
1160   }
1161 }
1162
1163 static void
1164 dissect_classification_ex_header(tvbuff_t *tvb,  packet_info *pinfo, proto_tree *tree, int idx)
1165 {
1166   if (tree) {
1167     proto_item *flags_item;
1168     proto_tree *flags_tree;
1169     guint64     hdr   = pinfo->pseudo_header->erf.ehdr_list[idx].ehdr;
1170     guint32     value = ((guint32)(hdr >> 32)) & EHDR_CLASS_FLAGS_MASK;
1171
1172     flags_item = proto_tree_add_uint(tree, hf_erf_ehdr_class_flags, tvb, 0, 0, value);
1173     flags_tree = proto_item_add_subtree(flags_item, ett_erf_flags);
1174
1175     proto_tree_add_uint(flags_tree, hf_erf_ehdr_class_flags_sh,   tvb, 0, 0, value);
1176     proto_tree_add_uint(flags_tree, hf_erf_ehdr_class_flags_shm,  tvb, 0, 0, value);
1177     proto_tree_add_uint(flags_tree, hf_erf_ehdr_class_flags_res1, tvb, 0, 0, value);
1178     proto_tree_add_uint(flags_tree, hf_erf_ehdr_class_flags_user, tvb, 0, 0, value);
1179     proto_tree_add_uint(flags_tree, hf_erf_ehdr_class_flags_res2, tvb, 0, 0, value);
1180     proto_tree_add_uint(flags_tree, hf_erf_ehdr_class_flags_drop, tvb, 0, 0, value);
1181     proto_tree_add_uint(flags_tree, hf_erf_ehdr_class_flags_str,  tvb, 0, 0, value);
1182
1183     proto_tree_add_uint(tree, hf_erf_ehdr_class_seqnum, tvb, 0, 0, (guint32)hdr);
1184   }
1185 }
1186
1187 static void
1188 dissect_intercept_ex_header(tvbuff_t *tvb,  packet_info *pinfo, proto_tree *tree, int idx)
1189 {
1190   if (tree) {
1191     guint64     hdr = pinfo->pseudo_header->erf.ehdr_list[idx].ehdr;
1192
1193     proto_tree_add_uint(tree, hf_erf_ehdr_int_res1, tvb, 0, 0, (guint8)((hdr >> 48) & 0xFF));
1194     proto_tree_add_uint(tree, hf_erf_ehdr_int_id, tvb, 0, 0, (guint16)((hdr >> 32 ) & 0xFFFF));
1195     proto_tree_add_uint(tree, hf_erf_ehdr_int_res2, tvb, 0, 0, (guint32)hdr);
1196   }
1197 }
1198
1199 static void
1200 dissect_raw_link_ex_header(tvbuff_t *tvb,  packet_info *pinfo, proto_tree *tree, int idx)
1201 {
1202   if (tree) {
1203     guint64     hdr = pinfo->pseudo_header->erf.ehdr_list[idx].ehdr;
1204
1205     proto_tree_add_uint(tree, hf_erf_ehdr_raw_link_res ,    tvb, 0, 0, (guint32)((hdr >> 32) & 0xFFFFFF));
1206     proto_tree_add_uint(tree, hf_erf_ehdr_raw_link_seqnum , tvb, 0, 0, (guint32)((hdr >> 16) & 0xffff));
1207     proto_tree_add_uint(tree, hf_erf_ehdr_raw_link_rate,    tvb, 0, 0, (guint32)((hdr >> 8) & 0x00ff));
1208     proto_tree_add_uint(tree, hf_erf_ehdr_raw_link_type,    tvb, 0, 0, (guint32)(hdr & 0x00ff));
1209   }
1210 }
1211
1212 static void
1213 dissect_bfs_ex_header(tvbuff_t *tvb,  packet_info *pinfo, proto_tree *tree, int idx)
1214 {
1215   if (tree) {
1216     guint64     hdr = pinfo->pseudo_header->erf.ehdr_list[idx].ehdr;
1217
1218     proto_tree_add_uint(tree, hf_erf_ehdr_bfs_hash, tvb, 0, 0, (guint32)((hdr >> 48) & 0xFF));
1219     proto_tree_add_uint(tree, hf_erf_ehdr_bfs_color, tvb, 0, 0, (guint32)((hdr >> 32) & 0xFFFF));
1220     proto_tree_add_uint(tree, hf_erf_ehdr_bfs_raw_hash, tvb, 0, 0, (guint32)(hdr & 0xFFFFFFFF));
1221   }
1222 }
1223
1224 static int
1225 channelised_fill_sdh_g707_format(sdh_g707_format_t* in_fmt, guint16 bit_flds, guint8 vc_size, guint8 rate)
1226 {
1227   int i = 0; /* i = 3 --> ITU-T letter #D - index of AUG-16
1228               * i = 2 --> ITU-T letter #C - index of AUG-4,
1229               * i = 1 --> ITU-T letter #B - index of AUG-1
1230               * i = 0 --> ITU-T letter #A - index of AU3*/
1231
1232   if ( (0 == vc_size) || (vc_size > DECHAN_MAX_VC_SIZE) || (rate > DECHAN_MAX_LINE_RATE) )
1233   {
1234     /* unknown / unused / invalid container size or invalid line rate */
1235     in_fmt->m_vc_size = 0;
1236     in_fmt->m_sdh_line_rate = 0;
1237     memset(&(in_fmt->m_vc_index_array[0]), 0x00, DECHAN_MAX_AUG_INDEX);
1238     return -1;
1239   }
1240
1241   in_fmt->m_vc_size = vc_size;
1242   in_fmt->m_sdh_line_rate = rate;
1243   memset(&(in_fmt->m_vc_index_array[0]), 0xff, DECHAN_MAX_AUG_INDEX);
1244
1245   /* for STM64 traffic,from #D and so on .. */
1246     for (i = (rate - 2); i >= 0; i--)
1247   {
1248     guint8 aug_n_index = 0;
1249
1250     /*if AUG-n is bigger than vc-size*/
1251     if ( i >= (vc_size - 1))
1252     {
1253       /* check the value in bit flds */
1254       aug_n_index = ((bit_flds >> (2 *i))& 0x3) +1;
1255     }
1256     else
1257     {
1258       aug_n_index = 0;
1259     }
1260     in_fmt->m_vc_index_array[i] = aug_n_index;
1261   }
1262   return 0;
1263 }
1264
1265 static void
1266 channelised_fill_vc_id_string(wmem_strbuf_t* out_string, sdh_g707_format_t* in_fmt)
1267 {
1268   int      i;
1269   gboolean is_printed  = FALSE;
1270
1271   static const char* g_vc_size_strings[] = {
1272     "unknown",  /*0x0*/
1273     "VC3",      /*0x1*/
1274     "VC4",      /*0x2*/
1275     "VC4-4c",   /*0x3*/
1276     "VC4-16c",  /*0x4*/
1277     "VC4-64c",  /*0x5*/};
1278
1279   wmem_strbuf_truncate(out_string, 0);
1280
1281   if ( (in_fmt->m_vc_size > DECHAN_MAX_VC_SIZE) || (in_fmt->m_sdh_line_rate > DECHAN_MAX_LINE_RATE) )
1282   {
1283     wmem_strbuf_append_printf(out_string, "Malformed");
1284     return;
1285   }
1286
1287   wmem_strbuf_append_printf(out_string, "%s(",
1288                             (in_fmt->m_vc_size < array_length(g_vc_size_strings)) ?
1289                             g_vc_size_strings[in_fmt->m_vc_size] : g_vc_size_strings[0] );
1290
1291   if (in_fmt->m_sdh_line_rate <= 0 )
1292   {
1293     /* line rate is not given */
1294     for (i = (DECHAN_MAX_AUG_INDEX -1); i >= 0; i--)
1295     {
1296       if ((in_fmt->m_vc_index_array[i] > 0) || (is_printed) )
1297       {
1298         wmem_strbuf_append_printf(out_string, "%s%d",
1299                                   ((is_printed)?", ":""),
1300                                   in_fmt->m_vc_index_array[i]);
1301         is_printed = TRUE;
1302       }
1303     }
1304
1305   }
1306   else
1307   {
1308     for (i = in_fmt->m_sdh_line_rate - 2; i >= 0; i--)
1309     {
1310       wmem_strbuf_append_printf(out_string, "%s%d",
1311                                 ((is_printed)?", ":""),
1312                                 in_fmt->m_vc_index_array[i]);
1313       is_printed = TRUE;
1314     }
1315   }
1316   if ( ! is_printed )
1317   {
1318     /* Not printed . possibly it's a ocXc packet with (0,0,0...) */
1319     for ( i =0; i < in_fmt->m_vc_size - 2; i++)
1320     {
1321       wmem_strbuf_append_printf(out_string, "%s0",
1322                                 ((is_printed)?", ":""));
1323       is_printed = TRUE;
1324     }
1325   }
1326   wmem_strbuf_append_c(out_string, ')');
1327   return;
1328 }
1329
1330 static void
1331 dissect_channelised_ex_header(tvbuff_t *tvb,  packet_info *pinfo, proto_tree *tree, int idx)
1332 {
1333   guint64            hdr              = pinfo->pseudo_header->erf.ehdr_list[idx].ehdr;
1334   guint8             vc_id            = (guint8)((hdr >> 24) & 0xFF);
1335   guint8             vc_size          = (guint8)((hdr >> 16) & 0xFF);
1336   guint8             line_rate        = (guint8)((hdr >> 8) & 0xFF);
1337   sdh_g707_format_t  g707_format;
1338   wmem_strbuf_t     *vc_id_string = wmem_strbuf_new_label(wmem_packet_scope());
1339
1340   channelised_fill_sdh_g707_format(&g707_format, vc_id, vc_size, line_rate);
1341   channelised_fill_vc_id_string(vc_id_string, &g707_format);
1342
1343   if (tree) {
1344     proto_tree_add_boolean(tree, hf_erf_ehdr_chan_morebits, tvb, 0, 0, (guint8)((hdr >> 63) & 0x1));
1345     proto_tree_add_boolean(tree, hf_erf_ehdr_chan_morefrag, tvb, 0, 0, (guint8)((hdr >> 55) & 0x1));
1346     proto_tree_add_uint(tree, hf_erf_ehdr_chan_seqnum, tvb, 0, 0, (guint16)((hdr >> 40) & 0x7FFF));
1347     proto_tree_add_uint(tree, hf_erf_ehdr_chan_res, tvb, 0, 0, (guint8)((hdr >> 32) & 0xFF));
1348     proto_tree_add_uint_format_value(tree, hf_erf_ehdr_chan_virt_container_id, tvb, 0, 0, vc_id,
1349                                      "0x%.2x (g.707: %s)", vc_id, wmem_strbuf_get_str(vc_id_string));
1350     proto_tree_add_uint(tree, hf_erf_ehdr_chan_assoc_virt_container_size, tvb, 0, 0, vc_size);
1351     proto_tree_add_uint(tree, hf_erf_ehdr_chan_rate, tvb, 0, 0, line_rate);
1352     proto_tree_add_uint(tree, hf_erf_ehdr_chan_type, tvb, 0, 0, (guint8)((hdr >> 0) & 0xFF));
1353   }
1354 }
1355
1356 static void
1357 dissect_signature_ex_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int idx)
1358 {
1359   if(tree) {
1360     guint64     hdr = pinfo->pseudo_header->erf.ehdr_list[idx].ehdr;
1361
1362     proto_tree_add_uint(tree, hf_erf_ehdr_signature_payload_hash, tvb, 0, 0, (guint32)((hdr >> 32) & 0xFFFFFF));
1363     proto_tree_add_uint(tree, hf_erf_ehdr_signature_color,        tvb, 0, 0, (guint8)((hdr >> 24) & 0xFF));
1364     proto_tree_add_uint(tree, hf_erf_ehdr_signature_flow_hash,    tvb, 0, 0, (guint32)(hdr & 0xFFFFFF));
1365   }
1366 }
1367
1368 static void
1369 dissect_host_id_ex_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int idx)
1370 {
1371   if(tree) {
1372     guint64     hdr = pinfo->pseudo_header->erf.ehdr_list[idx].ehdr;
1373
1374     proto_tree_add_uint(tree, hf_erf_ehdr_host_id_sourceid, tvb, 0, 0, (guint8)((hdr >> 48) & 0xFF));
1375     proto_tree_add_uint64(tree, hf_erf_ehdr_host_id_hostid, tvb, 0, 0, (hdr & ERF_EHDR_HOST_ID_MASK));
1376   }
1377 }
1378
1379 static void
1380 dissect_flow_id_ex_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int idx)
1381 {
1382   if(tree) {
1383     guint64     hdr = pinfo->pseudo_header->erf.ehdr_list[idx].ehdr;
1384
1385     proto_tree_add_uint(tree, hf_erf_ehdr_flow_id_source_id,  tvb, 0, 0, (guint8)((hdr >> 48) & 0xFF));
1386     proto_tree_add_uint(tree, hf_erf_ehdr_flow_id_hash_type,  tvb, 0, 0, (guint8)((hdr >> 40) & 0xFF));
1387     proto_tree_add_uint(tree, hf_erf_ehdr_flow_id_stack_type, tvb, 0, 0, (guint8)((hdr >> 32) & 0xFF));
1388     proto_tree_add_uint(tree, hf_erf_ehdr_flow_id_flow_hash,  tvb, 0, 0, (guint32)(hdr & 0xFFFFFFFF));
1389   }
1390 }
1391
1392 static guint64
1393 find_host_id(packet_info *pinfo) {
1394   guint64 *hdr = NULL;
1395
1396   hdr = erf_get_ehdr(pinfo, ERF_EXT_HDR_TYPE_HOST_ID, NULL);
1397
1398   return hdr ? (*hdr & ERF_EHDR_HOST_ID_MASK) : 0;
1399 }
1400
1401 static void
1402 dissect_host_id_source_id(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint64 host_id, guint8 source_id)
1403 {
1404   if (tree) {
1405     proto_tree *hostid_tree;
1406     proto_item *pi           = NULL;
1407     guint32     fnum_current = G_MAXUINT32;
1408     guint32     fnum         = G_MAXUINT32;
1409     guint32     fnum_next    = G_MAXUINT32;
1410
1411     fnum = erf_source_find_closest(host_id, source_id, pinfo->num, &fnum_next);
1412
1413     if (fnum != G_MAXUINT32) {
1414       fnum_current = fnum;
1415     } else {
1416       /* XXX: Possibly undesireable side effect: first metadata record links to next */
1417       fnum_current = fnum_next;
1418     }
1419
1420     if (fnum_current != G_MAXUINT32) {
1421       pi = proto_tree_add_uint_format(tree, hf_erf_source_current, tvb, 0, 0, fnum_current,
1422           "Host ID: 0x%012" G_GINT64_MODIFIER "x, Source ID: %u", host_id, source_id&0xFF);
1423       hostid_tree = proto_item_add_subtree(pi, ett_erf_source);
1424     } else {
1425       /* If we have no frame number to link against, just add a static subtree */
1426       hostid_tree = proto_tree_add_subtree_format(tree, tvb, 0, 0, ett_erf_source, &pi,
1427           "Host ID: 0x%012" G_GINT64_MODIFIER "x, Source ID: %u", host_id, source_id&0xFF);
1428     }
1429     PROTO_ITEM_SET_GENERATED(pi);
1430
1431     pi = proto_tree_add_uint64(hostid_tree, hf_erf_hostid, tvb, 0, 0, host_id);
1432     PROTO_ITEM_SET_GENERATED(pi);
1433     pi = proto_tree_add_uint(hostid_tree, hf_erf_sourceid, tvb, 0, 0, source_id);
1434     PROTO_ITEM_SET_GENERATED(pi);
1435
1436     if (fnum_next != G_MAXUINT32) {
1437       pi = proto_tree_add_uint(hostid_tree, hf_erf_source_next, tvb, 0, 0, fnum_next);
1438       PROTO_ITEM_SET_GENERATED(pi);
1439     }
1440     if (fnum != G_MAXUINT32) {
1441       pi = proto_tree_add_uint(hostid_tree, hf_erf_source_prev, tvb, 0, 0, fnum);
1442       PROTO_ITEM_SET_GENERATED(pi);
1443     }
1444   }
1445 }
1446
1447 static void
1448 dissect_unknown_ex_header(tvbuff_t *tvb,  packet_info *pinfo, proto_tree *tree, int idx)
1449 {
1450   if (tree) {
1451     guint64     hdr = pinfo->pseudo_header->erf.ehdr_list[idx].ehdr;
1452
1453     proto_tree_add_uint64(tree, hf_erf_ehdr_unk, tvb, 0, 0, hdr);
1454   }
1455 }
1456
1457 static void
1458 dissect_mc_hdlc_header(tvbuff_t *tvb,  packet_info *pinfo, proto_tree *tree)
1459 {
1460   if (tree) {
1461     proto_item *mc_hdlc_item;
1462     proto_tree *mc_hdlc_tree;
1463     guint32     mc_hdlc;
1464     proto_item *pi;
1465
1466     /* Multi Channel HDLC Header */
1467     mc_hdlc_item = proto_tree_add_uint(tree, hf_erf_mc_hdlc, tvb, 0, 0, pinfo->pseudo_header->erf.subhdr.mc_hdr);
1468     mc_hdlc_tree = proto_item_add_subtree(mc_hdlc_item, ett_erf_mc_hdlc);
1469     mc_hdlc = pinfo->pseudo_header->erf.subhdr.mc_hdr;
1470
1471     proto_tree_add_uint(mc_hdlc_tree, hf_erf_mc_hdlc_cn, tvb, 0, 0,  mc_hdlc);
1472     proto_tree_add_uint(mc_hdlc_tree, hf_erf_mc_hdlc_res1, tvb, 0, 0,  mc_hdlc);
1473     proto_tree_add_uint(mc_hdlc_tree, hf_erf_mc_hdlc_res2, tvb, 0, 0,  mc_hdlc);
1474     pi=proto_tree_add_uint(mc_hdlc_tree, hf_erf_mc_hdlc_fcse, tvb, 0, 0,  mc_hdlc);
1475     if (mc_hdlc & MC_HDLC_FCSE_MASK)
1476       expert_add_info_format(pinfo, pi, &ei_erf_checksum_error, "ERF MC FCS Error");
1477
1478     pi=proto_tree_add_uint(mc_hdlc_tree, hf_erf_mc_hdlc_sre,  tvb, 0, 0,  mc_hdlc);
1479     if (mc_hdlc & MC_HDLC_SRE_MASK)
1480       expert_add_info_format(pinfo, pi, &ei_erf_checksum_error, "ERF MC Short Record Error, <5 bytes");
1481
1482     pi=proto_tree_add_uint(mc_hdlc_tree, hf_erf_mc_hdlc_lre,  tvb, 0, 0,  mc_hdlc);
1483     if (mc_hdlc & MC_HDLC_LRE_MASK)
1484       expert_add_info_format(pinfo, pi, &ei_erf_checksum_error, "ERF MC Long Record Error, >2047 bytes");
1485
1486     pi=proto_tree_add_uint(mc_hdlc_tree, hf_erf_mc_hdlc_afe,  tvb, 0, 0,  mc_hdlc);
1487     if (mc_hdlc & MC_HDLC_AFE_MASK)
1488       expert_add_info_format(pinfo, pi, &ei_erf_checksum_error, "ERF MC Aborted Frame Error");
1489
1490     pi=proto_tree_add_uint(mc_hdlc_tree, hf_erf_mc_hdlc_oe,   tvb, 0, 0,  mc_hdlc);
1491     if (mc_hdlc & MC_HDLC_OE_MASK)
1492       expert_add_info_format(pinfo, pi, &ei_erf_checksum_error, "ERF MC Octet Error, the closing flag was not octet aligned after bit unstuffing");
1493
1494     pi=proto_tree_add_uint(mc_hdlc_tree, hf_erf_mc_hdlc_lbe,  tvb, 0, 0,  mc_hdlc);
1495     if (mc_hdlc & MC_HDLC_LBE_MASK)
1496       expert_add_info_format(pinfo, pi, &ei_erf_checksum_error, "ERF MC Lost Byte Error");
1497
1498     proto_tree_add_uint(mc_hdlc_tree, hf_erf_mc_hdlc_first, tvb, 0, 0,  mc_hdlc);
1499     proto_tree_add_uint(mc_hdlc_tree, hf_erf_mc_hdlc_res3,  tvb, 0, 0,  mc_hdlc);
1500   }
1501 }
1502
1503 static void
1504 dissect_mc_raw_header(tvbuff_t *tvb,  packet_info *pinfo, proto_tree *tree)
1505 {
1506   if (tree) {
1507     proto_item *mc_raw_item;
1508     proto_tree *mc_raw_tree;
1509     guint32     mc_raw;
1510
1511     /* Multi Channel RAW Header */
1512     mc_raw_item = proto_tree_add_uint(tree, hf_erf_mc_raw, tvb, 0, 0, pinfo->pseudo_header->erf.subhdr.mc_hdr);
1513     mc_raw_tree = proto_item_add_subtree(mc_raw_item, ett_erf_mc_raw);
1514     mc_raw = pinfo->pseudo_header->erf.subhdr.mc_hdr;
1515
1516     proto_tree_add_uint(mc_raw_tree, hf_erf_mc_raw_int,   tvb, 0, 0, mc_raw);
1517     proto_tree_add_uint(mc_raw_tree, hf_erf_mc_raw_res1,  tvb, 0, 0, mc_raw);
1518     proto_tree_add_uint(mc_raw_tree, hf_erf_mc_raw_sre,   tvb, 0, 0, mc_raw);
1519     proto_tree_add_uint(mc_raw_tree, hf_erf_mc_raw_lre,   tvb, 0, 0, mc_raw);
1520     proto_tree_add_uint(mc_raw_tree, hf_erf_mc_raw_res2,  tvb, 0, 0, mc_raw);
1521     proto_tree_add_uint(mc_raw_tree, hf_erf_mc_raw_lbe,   tvb, 0, 0, mc_raw);
1522     proto_tree_add_uint(mc_raw_tree, hf_erf_mc_raw_first, tvb, 0, 0, mc_raw);
1523     proto_tree_add_uint(mc_raw_tree, hf_erf_mc_raw_res3,  tvb, 0, 0, mc_raw);
1524   }
1525 }
1526
1527 static void
1528 dissect_mc_atm_header(tvbuff_t *tvb,  packet_info *pinfo, proto_tree *tree)
1529 {
1530   if (tree) {
1531     proto_item *mc_atm_item;
1532     proto_tree *mc_atm_tree;
1533     guint32     mc_atm;
1534
1535     /*"Multi Channel ATM Header"*/
1536     mc_atm_item = proto_tree_add_uint(tree, hf_erf_mc_atm, tvb, 0, 0, pinfo->pseudo_header->erf.subhdr.mc_hdr);
1537     mc_atm_tree = proto_item_add_subtree(mc_atm_item, ett_erf_mc_atm);
1538     mc_atm = pinfo->pseudo_header->erf.subhdr.mc_hdr;
1539
1540     proto_tree_add_uint(mc_atm_tree, hf_erf_mc_atm_cn,      tvb, 0, 0, mc_atm);
1541     proto_tree_add_uint(mc_atm_tree, hf_erf_mc_atm_res1,    tvb, 0, 0, mc_atm);
1542     proto_tree_add_uint(mc_atm_tree, hf_erf_mc_atm_mul,     tvb, 0, 0, mc_atm);
1543
1544     proto_tree_add_uint(mc_atm_tree, hf_erf_mc_atm_port,    tvb, 0, 0, mc_atm);
1545     proto_tree_add_uint(mc_atm_tree, hf_erf_mc_atm_res2,    tvb, 0, 0, mc_atm);
1546
1547     proto_tree_add_uint(mc_atm_tree, hf_erf_mc_atm_lbe,     tvb, 0, 0, mc_atm);
1548     proto_tree_add_uint(mc_atm_tree, hf_erf_mc_atm_hec,     tvb, 0, 0, mc_atm);
1549     proto_tree_add_uint(mc_atm_tree, hf_erf_mc_atm_crc10,   tvb, 0, 0, mc_atm);
1550     proto_tree_add_uint(mc_atm_tree, hf_erf_mc_atm_oamcell, tvb, 0, 0, mc_atm);
1551     proto_tree_add_uint(mc_atm_tree, hf_erf_mc_atm_first,   tvb, 0, 0, mc_atm);
1552     proto_tree_add_uint(mc_atm_tree, hf_erf_mc_atm_res3,    tvb, 0, 0, mc_atm);
1553   }
1554 }
1555
1556 static void
1557 dissect_mc_rawlink_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1558 {
1559   if (tree) {
1560     proto_item *mc_rawl_item;
1561     proto_tree *mc_rawl_tree;
1562     guint32     mc_rawl;
1563
1564     /* Multi Channel RAW Link Header */
1565     mc_rawl_item = proto_tree_add_uint(tree, hf_erf_mc_rawl, tvb, 0, 0, pinfo->pseudo_header->erf.subhdr.mc_hdr);
1566     mc_rawl_tree = proto_item_add_subtree(mc_rawl_item, ett_erf_mc_rawlink);
1567     mc_rawl = pinfo->pseudo_header->erf.subhdr.mc_hdr;
1568
1569     proto_tree_add_uint(mc_rawl_tree, hf_erf_mc_rawl_cn,    tvb, 0, 0, mc_rawl);
1570     proto_tree_add_uint(mc_rawl_tree, hf_erf_mc_rawl_res1,  tvb, 0, 0, mc_rawl);
1571     proto_tree_add_uint(mc_rawl_tree, hf_erf_mc_rawl_lbe,   tvb, 0, 0, mc_rawl);
1572     proto_tree_add_uint(mc_rawl_tree, hf_erf_mc_rawl_first, tvb, 0, 0, mc_rawl);
1573     proto_tree_add_uint(mc_rawl_tree, hf_erf_mc_rawl_res2,  tvb, 0, 0, mc_rawl);
1574   }
1575 }
1576
1577 static void
1578 dissect_mc_aal5_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1579 {
1580   if (tree) {
1581     proto_item *mc_aal5_item;
1582     proto_tree *mc_aal5_tree;
1583     guint32     mc_aal5;
1584
1585     /* Multi Channel AAL5 Header */
1586     mc_aal5_item = proto_tree_add_uint(tree, hf_erf_mc_aal5, tvb, 0, 0, pinfo->pseudo_header->erf.subhdr.mc_hdr);
1587     mc_aal5_tree = proto_item_add_subtree(mc_aal5_item, ett_erf_mc_aal5);
1588     mc_aal5 = pinfo->pseudo_header->erf.subhdr.mc_hdr;
1589
1590     proto_tree_add_uint(mc_aal5_tree, hf_erf_mc_aal5_cn,    tvb, 0, 0, mc_aal5);
1591     proto_tree_add_uint(mc_aal5_tree, hf_erf_mc_aal5_res1,  tvb, 0, 0, mc_aal5);
1592
1593     proto_tree_add_uint(mc_aal5_tree, hf_erf_mc_aal5_port,  tvb, 0, 0, mc_aal5);
1594     proto_tree_add_uint(mc_aal5_tree, hf_erf_mc_aal5_crcck, tvb, 0, 0, mc_aal5);
1595     proto_tree_add_uint(mc_aal5_tree, hf_erf_mc_aal5_crce,  tvb, 0, 0, mc_aal5);
1596     proto_tree_add_uint(mc_aal5_tree, hf_erf_mc_aal5_lenck, tvb, 0, 0, mc_aal5);
1597     proto_tree_add_uint(mc_aal5_tree, hf_erf_mc_aal5_lene,  tvb, 0, 0, mc_aal5);
1598
1599     proto_tree_add_uint(mc_aal5_tree, hf_erf_mc_aal5_res2,  tvb, 0, 0, mc_aal5);
1600     proto_tree_add_uint(mc_aal5_tree, hf_erf_mc_aal5_first, tvb, 0, 0, mc_aal5);
1601     proto_tree_add_uint(mc_aal5_tree, hf_erf_mc_aal5_res3,  tvb, 0, 0, mc_aal5);
1602   }
1603 }
1604
1605 static void
1606 dissect_mc_aal2_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1607 {
1608   if (tree) {
1609     proto_item *mc_aal2_item;
1610     proto_tree *mc_aal2_tree;
1611     guint32     mc_aal2;
1612
1613     /* Multi Channel AAL2 Header */
1614     mc_aal2_item = proto_tree_add_uint(tree, hf_erf_mc_aal2, tvb, 0, 0, pinfo->pseudo_header->erf.subhdr.mc_hdr);
1615     mc_aal2_tree = proto_item_add_subtree(mc_aal2_item, ett_erf_mc_aal2);
1616     mc_aal2 = pinfo->pseudo_header->erf.subhdr.mc_hdr;
1617
1618     proto_tree_add_uint(mc_aal2_tree, hf_erf_mc_aal2_cn,    tvb, 0, 0, mc_aal2);
1619     proto_tree_add_uint(mc_aal2_tree, hf_erf_mc_aal2_res1,  tvb, 0, 0, mc_aal2);
1620     proto_tree_add_uint(mc_aal2_tree, hf_erf_mc_aal2_res2,  tvb, 0, 0, mc_aal2);
1621
1622     proto_tree_add_uint(mc_aal2_tree, hf_erf_mc_aal2_port,  tvb, 0, 0, mc_aal2);
1623     proto_tree_add_uint(mc_aal2_tree, hf_erf_mc_aal2_res3,  tvb, 0, 0, mc_aal2);
1624     proto_tree_add_uint(mc_aal2_tree, hf_erf_mc_aal2_first, tvb, 0, 0, mc_aal2);
1625     proto_tree_add_uint(mc_aal2_tree, hf_erf_mc_aal2_maale, tvb, 0, 0, mc_aal2);
1626     proto_tree_add_uint(mc_aal2_tree, hf_erf_mc_aal2_lene,  tvb, 0, 0, mc_aal2);
1627
1628     proto_tree_add_uint(mc_aal2_tree, hf_erf_mc_aal2_cid,   tvb, 0, 0, mc_aal2);
1629   }
1630 }
1631
1632 static void
1633 dissect_aal2_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1634 {
1635   if (tree) {
1636     proto_item *aal2_item;
1637     proto_tree *aal2_tree;
1638     guint32     aal2;
1639
1640     /* AAL2 Header */
1641     aal2_item = proto_tree_add_uint(tree, hf_erf_aal2, tvb, 0, 0, pinfo->pseudo_header->erf.subhdr.mc_hdr);
1642     aal2_tree = proto_item_add_subtree(aal2_item, ett_erf_aal2);
1643     aal2 = pinfo->pseudo_header->erf.subhdr.aal2_hdr;
1644
1645     proto_tree_add_uint(aal2_tree, hf_erf_aal2_cid,    tvb, 0, 0, aal2);
1646
1647     proto_tree_add_uint(aal2_tree, hf_erf_aal2_maale,  tvb, 0, 0, aal2);
1648
1649     proto_tree_add_uint(aal2_tree, hf_erf_aal2_maalei, tvb, 0, 0, aal2);
1650     proto_tree_add_uint(aal2_tree, hf_erf_aal2_first,  tvb, 0, 0, aal2);
1651     proto_tree_add_uint(aal2_tree, hf_erf_aal2_res1,   tvb, 0, 0, aal2);
1652   }
1653 }
1654
1655 static void
1656 dissect_eth_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1657 {
1658   if (tree) {
1659     proto_item          *eth_item;
1660     proto_tree          *eth_tree;
1661     guint8               eth_offset, eth_pad;
1662
1663     eth_item = proto_tree_add_item(tree, hf_erf_eth, tvb, 0, 0, ENC_NA);
1664
1665     eth_tree = proto_item_add_subtree(eth_item, ett_erf_eth);
1666     eth_offset = pinfo->pseudo_header->erf.subhdr.eth_hdr.offset;
1667     eth_pad = pinfo->pseudo_header->erf.subhdr.eth_hdr.pad;
1668
1669     proto_tree_add_uint(eth_tree, hf_erf_eth_off, tvb, 0, 0, eth_offset);
1670     proto_tree_add_uint(eth_tree, hf_erf_eth_pad, tvb, 0, 0, eth_pad);
1671   }
1672 }
1673
1674 static void
1675 dissect_erf_pseudo_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1676 {
1677   proto_item *pi;
1678   proto_item *flags_item, *rectype_item;
1679   proto_tree *flags_tree, *rectype_tree;
1680
1681   proto_tree_add_uint64(tree, hf_erf_ts, tvb, 0, 0, pinfo->pseudo_header->erf.phdr.ts);
1682
1683   rectype_item = proto_tree_add_uint_format_value(tree, hf_erf_rectype, tvb, 0, 0, pinfo->pseudo_header->erf.phdr.type,
1684                                                   "0x%02x (Type %d: %s)",
1685                                                   pinfo->pseudo_header->erf.phdr.type,
1686                                                   pinfo->pseudo_header->erf.phdr.type & ERF_HDR_TYPE_MASK,
1687                                                   val_to_str_const(
1688                                                     pinfo->pseudo_header->erf.phdr.type & ERF_HDR_TYPE_MASK,
1689                                                     erf_type_vals,
1690                                                     "Unknown Type"));
1691
1692   rectype_tree = proto_item_add_subtree(rectype_item, ett_erf_rectype);
1693   proto_tree_add_uint(rectype_tree, hf_erf_type, tvb, 0, 0, pinfo->pseudo_header->erf.phdr.type);
1694   proto_tree_add_uint(rectype_tree, hf_erf_ehdr, tvb, 0, 0, pinfo->pseudo_header->erf.phdr.type);
1695
1696   flags_item=proto_tree_add_uint(tree, hf_erf_flags, tvb, 0, 0, pinfo->pseudo_header->erf.phdr.flags);
1697   flags_tree = proto_item_add_subtree(flags_item, ett_erf_flags);
1698
1699   proto_tree_add_uint(flags_tree, hf_erf_flags_cap, tvb, 0, 0, pinfo->pseudo_header->erf.phdr.flags);
1700   proto_item_append_text(flags_item, " (Capture Interface: %d", pinfo->pseudo_header->erf.phdr.flags & ERF_HDR_CAP_MASK);
1701
1702   proto_tree_add_uint(flags_tree, hf_erf_flags_vlen, tvb, 0, 0, pinfo->pseudo_header->erf.phdr.flags);
1703   pi=proto_tree_add_uint(flags_tree, hf_erf_flags_trunc, tvb, 0, 0, pinfo->pseudo_header->erf.phdr.flags);
1704   if (pinfo->pseudo_header->erf.phdr.flags & ERF_HDR_TRUNC_MASK) {
1705     proto_item_append_text(flags_item, "; ERF Truncation Error");
1706     expert_add_info_format(pinfo, pi, &ei_erf_checksum_error, "ERF Truncation Error");
1707   }
1708
1709   pi=proto_tree_add_uint(flags_tree, hf_erf_flags_rxe, tvb, 0, 0, pinfo->pseudo_header->erf.phdr.flags);
1710   if (pinfo->pseudo_header->erf.phdr.flags & ERF_HDR_RXE_MASK) {
1711     proto_item_append_text(flags_item, "; ERF Rx Error");
1712     expert_add_info_format(pinfo, pi, &ei_erf_checksum_error, "ERF Rx Error");
1713   }
1714
1715   pi=proto_tree_add_uint(flags_tree, hf_erf_flags_dse, tvb, 0, 0, pinfo->pseudo_header->erf.phdr.flags);
1716   if (pinfo->pseudo_header->erf.phdr.flags & ERF_HDR_DSE_MASK) {
1717     proto_item_append_text(flags_item, "; ERF DS Error");
1718     expert_add_info_format(pinfo, pi, &ei_erf_checksum_error, "ERF DS Error");
1719   }
1720   proto_item_append_text(flags_item, ")");
1721
1722   proto_tree_add_uint(flags_tree, hf_erf_flags_res, tvb, 0, 0, pinfo->pseudo_header->erf.phdr.flags);
1723
1724   proto_tree_add_uint(tree, hf_erf_rlen, tvb, 0, 0, pinfo->pseudo_header->erf.phdr.rlen);
1725   pi=proto_tree_add_uint(tree, hf_erf_lctr, tvb, 0, 0, pinfo->pseudo_header->erf.phdr.lctr);
1726   if (pinfo->pseudo_header->erf.phdr.lctr > 0)
1727     expert_add_info(pinfo, pi, &ei_erf_packet_loss);
1728
1729   proto_tree_add_uint(tree, hf_erf_wlen, tvb, 0, 0, pinfo->pseudo_header->erf.phdr.wlen);
1730 }
1731
1732 static void
1733 dissect_erf_pseudo_extension_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1734 {
1735   proto_item *pi;
1736   proto_item *ehdr_tree;
1737   guint64     hdr;
1738   guint8      type;
1739   guint8      has_more = pinfo->pseudo_header->erf.phdr.type & 0x80;
1740   int         i        = 0;
1741   int         max      = sizeof(pinfo->pseudo_header->erf.ehdr_list)/sizeof(struct erf_ehdr);
1742
1743   guint64     host_id        = 0;
1744   guint8      source_id      = 0;
1745   guint64     host_id_last   = 0;
1746   guint8      source_id_last = 0;
1747
1748   /*
1749    * Get the first Host ID of the record (which may not be the first extension
1750    * header).
1751    */
1752   host_id = find_host_id(pinfo);
1753   if (host_id == 0) {
1754     /*
1755      * XXX: We are relying here on the Wireshark doing a second parse any
1756      * time it does anything with tree items (including filtering) to associate
1757      * the records before the first ERF_TYPE_META record. This does not work
1758      * with TShark in one-pass mode, in which case the first few records get
1759      * Host ID 0 (unset).
1760      */
1761     host_id = erf_state.implicit_host_id;
1762   }
1763
1764   while(has_more && (i < max)) {
1765     hdr = pinfo->pseudo_header->erf.ehdr_list[i].ehdr;
1766     type = (guint8) (hdr >> 56);
1767
1768     pi = proto_tree_add_uint(tree, hf_erf_ehdr_t, tvb, 0, 0, (type & 0x7f));
1769     ehdr_tree = proto_item_add_subtree(pi, ett_erf_pseudo_hdr);
1770
1771     switch (type & 0x7f) {
1772     case ERF_EXT_HDR_TYPE_CLASSIFICATION:
1773       dissect_classification_ex_header(tvb, pinfo, ehdr_tree, i);
1774       break;
1775     case ERF_EXT_HDR_TYPE_INTERCEPTID:
1776       dissect_intercept_ex_header(tvb, pinfo, ehdr_tree, i);
1777       break;
1778     case ERF_EXT_HDR_TYPE_RAW_LINK:
1779       dissect_raw_link_ex_header(tvb, pinfo, ehdr_tree, i);
1780       break;
1781     case ERF_EXT_HDR_TYPE_BFS:
1782       dissect_bfs_ex_header(tvb, pinfo, ehdr_tree, i);
1783       break;
1784     case ERF_EXT_HDR_TYPE_CHANNELISED:
1785       dissect_channelised_ex_header(tvb, pinfo, ehdr_tree, i);
1786       break;
1787     case ERF_EXT_HDR_TYPE_SIGNATURE:
1788       dissect_signature_ex_header(tvb, pinfo, ehdr_tree, i);
1789       break;
1790     case ERF_EXT_HDR_TYPE_FLOW_ID:
1791       source_id = (guint8)((hdr >> 48) & 0xFF);
1792       dissect_flow_id_ex_header(tvb, pinfo, ehdr_tree, i);
1793       break;
1794     case ERF_EXT_HDR_TYPE_HOST_ID:
1795       host_id = hdr & ERF_EHDR_HOST_ID_MASK;
1796       source_id = (guint8)((hdr >> 48) & 0xFF);
1797       dissect_host_id_ex_header(tvb, pinfo, ehdr_tree, i);
1798       break;
1799     default:
1800       dissect_unknown_ex_header(tvb, pinfo, ehdr_tree, i);
1801       break;
1802     }
1803
1804     /* Track and dissect combined Host ID and Source ID(s) */
1805     if (source_id != source_id_last || host_id != host_id_last) {
1806       /*
1807        * TODO: Do we also want to track Host ID 0 Source ID 0 records? These
1808        * are technically unassociated.
1809        */
1810       if (!PINFO_FD_VISITED(pinfo)) {
1811         if ((pinfo->pseudo_header->erf.phdr.type & 0x7f) == ERF_TYPE_META) {
1812           /* Update the implicit Host ID when ERF_TYPE_META */
1813           /* XXX: We currently assume there is only one in the whole file */
1814           if (erf_state.implicit_host_id == 0 && source_id > 0) {
1815             erf_state.implicit_host_id = host_id;
1816           }
1817
1818           /* Add to the sequence of ERF_TYPE_META records */
1819           erf_source_append(host_id, source_id, pinfo->num);
1820         }
1821       }
1822
1823       dissect_host_id_source_id(tvb, pinfo, tree, host_id, source_id);
1824     }
1825
1826     host_id_last = host_id;
1827     source_id_last = source_id;
1828
1829     has_more = type & 0x80;
1830     i += 1;
1831   }
1832   if (has_more) {
1833     proto_tree_add_expert(tree, pinfo, &ei_erf_extension_headers_not_shown, tvb, 0, 0);
1834   }
1835
1836 }
1837
1838 guint64* erf_get_ehdr(packet_info *pinfo, guint8 hdrtype, gint* afterindex) {
1839   guint8      type;
1840   guint8      has_more;
1841   int         max;
1842   int         i        = afterindex ? *afterindex + 1 : 0; /*allow specifying instance to start after for use in loop*/
1843
1844   if (!pinfo) /*XXX: how to determine if erf pseudo_header is valid?*/
1845       return NULL;
1846
1847   has_more = pinfo->pseudo_header->erf.phdr.type & 0x80;
1848   max      = sizeof(pinfo->pseudo_header->erf.ehdr_list)/sizeof(struct erf_ehdr);
1849
1850
1851   while(has_more && (i < max)) {
1852     type = (guint8) (pinfo->pseudo_header->erf.ehdr_list[i].ehdr >> 56);
1853
1854     if ((type & 0x7f) == (hdrtype & 0x7f)) {
1855          if (afterindex)
1856              *afterindex = i;
1857          return &pinfo->pseudo_header->erf.ehdr_list[i].ehdr;
1858     }
1859
1860     has_more = type & 0x80;
1861     i += 1;
1862   }
1863
1864   return NULL;
1865 }
1866
1867 static void
1868 check_section_length(packet_info *pinfo, proto_item *sectionlen_pi, int offset, int sectionoffset, int sectionlen) {
1869   if (sectionlen_pi) {
1870     if (offset - sectionoffset == sectionlen) {
1871       proto_item_append_text(sectionlen_pi, " [correct]");
1872     } else if (sectionlen != 0) {
1873       proto_item_append_text(sectionlen_pi, " [incorrect, should be %u]", offset - sectionoffset);
1874       expert_add_info(pinfo, sectionlen_pi, &ei_erf_meta_section_len_error);
1875     }
1876   }
1877 }
1878
1879 static void
1880 dissect_meta_record_tags(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
1881   proto_item *pi            = NULL;
1882   proto_item *tag_pi        = NULL;
1883   proto_item *tag_tree;
1884   proto_item *section_pi    = NULL;
1885   proto_item *section_tree  = tree;
1886   proto_item *sectionlen_pi = NULL;
1887
1888   guint16                sectiontype  = ERF_META_SECTION_NONE;
1889   guint16                tagtype      = 0;
1890   guint16                taglength    = 0;
1891   const gchar           *tagvalstring = NULL;
1892   erf_meta_tag_info_t   *tag_info;
1893
1894   /* Used for search entry and unknown tags */
1895   erf_meta_hf_template_t tag_template_unknown = { 0, { "Unknown", "unknown",
1896     FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } };
1897   erf_meta_tag_info_t    tag_info_local       = { 0, 0, &tag_template_unknown,
1898     ett_erf_meta_tag, hf_erf_meta_tag_unknown, NULL };
1899
1900   int     offset        = 0;
1901   int     sectionoffset = 0;
1902   guint16 sectionid     = 0;
1903   guint16 sectionlen    = 0;
1904
1905   /* Set column heading title*/
1906   col_set_str(pinfo->cinfo, COL_INFO, "MetaERF Record");
1907
1908   /* Go through the sectionss and their tags */
1909   while (tvb_captured_length_remaining(tvb, offset) > 4) {
1910     tagtype = tvb_get_ntohs(tvb, offset);
1911     taglength = tvb_get_ntohs(tvb, offset + 2);
1912     tag_tree = NULL;
1913
1914     if (ERF_META_IS_SECTION(tagtype))
1915       sectiontype = tagtype;
1916
1917     /* Look up per-section tag hf */
1918     tag_info_local.code = tagtype;
1919     tag_info_local.section = sectiontype;
1920     tag_info = (erf_meta_tag_info_t*) wmem_map_lookup(erf_meta_index.tag_table, GUINT_TO_POINTER(ERF_TAG_INFO_KEY(&tag_info_local)));
1921
1922     /* Fall back to unknown tag */
1923     if (tag_info == NULL)
1924       tag_info = &tag_info_local;
1925
1926     /* Dissect value, length and type */
1927     if (ERF_META_IS_SECTION(tagtype)) { /* Section header tag */
1928       if (section_pi) {
1929         /* Update section item length of last section */
1930         proto_item_set_len(section_pi, offset - sectionoffset);
1931         if (sectionlen_pi) {
1932           check_section_length(pinfo, sectionlen_pi, offset, sectionoffset, sectionlen);
1933         }
1934       }
1935
1936       sectionoffset = offset;
1937       if (tag_info->tag_template == &tag_template_unknown) {
1938         /* Unknown section */
1939         sectiontype = ERF_META_SECTION_UNKNOWN;
1940         tag_info = erf_meta_index.unknown_section_info;
1941       }
1942       DISSECTOR_ASSERT(tag_info->extra);
1943
1944       tagvalstring = val_to_str(tagtype, VALS(wmem_array_get_raw(erf_meta_index.vs_list)), "Unknown Section (0x%x)");
1945       section_tree = proto_tree_add_subtree_format(tree, tvb, offset, 0, tag_info->extra->ett_value, &section_pi, "MetaERF %s", tagvalstring);
1946       tag_tree = proto_tree_add_subtree_format(section_tree, tvb, offset, taglength + 4, tag_info->ett, &tag_pi, "%s Header", tagvalstring);
1947
1948       if (taglength > 0) {
1949         sectionid = tvb_get_ntohs(tvb, offset + 4);
1950         sectionlen = tvb_get_ntohs(tvb, offset + 6);
1951
1952         /* Add section_id */
1953         proto_tree_add_uint(tag_tree, tag_info->hf_value, tvb, offset + 4, 2, sectionid);
1954         if (sectionid != 0)
1955           proto_item_append_text(section_pi, " %u", sectionid);
1956
1957         /* Add section_len */
1958         sectionlen_pi = proto_tree_add_uint(tag_tree, tag_info->extra->hf_values[0], tvb, offset + 6, 2, sectionlen);
1959
1960         /* Reserved extra section header information */
1961         if (taglength > 4) {
1962           proto_tree_add_item(tag_tree, tag_info->extra->hf_values[1], tvb, offset + 8, taglength - 4, ENC_NA);
1963         }
1964       }
1965     } else { /* Not section header tag */
1966       enum ftenum tag_ft;
1967       char        pi_label[ITEM_LABEL_LENGTH+1];
1968       gboolean    dissected = TRUE;
1969       guint32     value32;
1970       guint64     value64;
1971       gchar      *tmp = NULL;
1972
1973       tag_ft = tag_info->tag_template->hfinfo.type;
1974       pi_label[0] = '\0';
1975
1976       /* Group tags before first section header into a fake section */
1977       if (offset == 0) {
1978         section_tree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_erf_meta, &section_pi, "MetaERF No Section");
1979       }
1980
1981       /* Handle special cases */
1982       /* TODO: might want to do this dynamically via tag_info callback */
1983       switch (tagtype) {
1984       /* TODO: use get_tcp_port in epan/addr_resolv.h etc */
1985       case ERF_META_TAG_if_speed:
1986       case ERF_META_TAG_if_tx_speed:
1987         value64 = tvb_get_ntoh64(tvb, offset + 4);
1988         tmp = format_size((gint64) value64, (format_size_flags_e)(format_size_unit_bits_s|format_size_prefix_si));
1989         tag_pi = proto_tree_add_uint64_format_value(section_tree, tag_info->hf_value, tvb, offset + 4, taglength, value64, "%s (%" G_GINT64_MODIFIER "u bps)", tmp, value64);
1990         g_free(tmp);
1991         break;
1992
1993       case ERF_META_TAG_if_rx_power:
1994       case ERF_META_TAG_if_tx_power:
1995         value32 = tvb_get_ntohl(tvb, offset + 4);
1996         tag_pi = proto_tree_add_int_format_value(section_tree, tag_info->hf_value, tvb, offset + 4, taglength, (gint32) value32, "%.2fdBm", (float)((gint32) value32)/100.0);
1997         break;
1998
1999       case ERF_META_TAG_loc_lat:
2000       case ERF_META_TAG_loc_long:
2001         value32 = tvb_get_ntohl(tvb, offset + 4);
2002         tag_pi = proto_tree_add_int_format_value(section_tree, tag_info->hf_value, tvb, offset + 4, taglength, (gint32) value32, "%.2f", (double)((gint32) value32)*1000000.0);
2003         break;
2004
2005       case ERF_META_TAG_mask_cidr:
2006         value32 = tvb_get_ntohl(tvb, offset + 4);
2007         tag_pi = proto_tree_add_uint_format_value(section_tree, tag_info->hf_value, tvb, offset + 4, taglength, value32, "/%u", value32);
2008         break;
2009
2010       case ERF_META_TAG_mem:
2011         value64 = tvb_get_ntoh64(tvb, offset + 4);
2012         tmp = format_size((gint64) value64, (format_size_flags_e)(format_size_unit_bytes|format_size_prefix_iec));
2013         tag_pi = proto_tree_add_uint64_format_value(section_tree, tag_info->hf_value, tvb, offset + 4, taglength, value64, "%s (%" G_GINT64_MODIFIER"u bytes)", tmp, value64);
2014         g_free(tmp);
2015         break;
2016
2017       case ERF_META_TAG_parent_section:
2018         DISSECTOR_ASSERT(tag_info->extra);
2019         value32 = tvb_get_ntohs(tvb, offset + 4);
2020         /*
2021          * XXX: Formatting value manually because don't have erf_meta_vs_list
2022          * populated at registration time.
2023          */
2024         tag_tree = proto_tree_add_subtree_format(section_tree, tvb, offset + 4, taglength, tag_info->ett, &tag_pi, "%s: %s %u", tag_info->tag_template->hfinfo.name,
2025             val_to_str(value32, VALS(wmem_array_get_raw(erf_meta_index.vs_list)), "Unknown Section (%u)"), tvb_get_ntohs(tvb, offset + 4 + 2));
2026
2027         proto_tree_add_uint_format_value(tag_tree, tag_info->hf_value, tvb, offset + 4, MIN(2, taglength), value32, "%s (%u)",
2028             val_to_str(value32, VALS(wmem_array_get_raw(erf_meta_index.vs_abbrev_list)), "Unknown"), value32);
2029         proto_tree_add_item(tag_tree, tag_info->extra->hf_values[0], tvb, offset + 6, MIN(2, taglength - 2), ENC_BIG_ENDIAN);
2030         break;
2031
2032       case ERF_META_TAG_reset:
2033         tag_pi = proto_tree_add_item(section_tree, tag_info->hf_value, tvb, offset + 4, taglength, ENC_NA);
2034         expert_add_info(pinfo, tag_pi, &ei_erf_meta_reset);
2035         break;
2036
2037       case ERF_META_TAG_if_link_status:
2038         DISSECTOR_ASSERT(tag_info->extra);
2039         {
2040           const int *link_status_flags[] = {
2041             &tag_info->extra->hf_values[0],
2042             NULL
2043           };
2044
2045           tag_pi = proto_tree_add_bitmask(section_tree, tvb, offset + 4, tag_info->hf_value, tag_info->ett, link_status_flags, ENC_BIG_ENDIAN);
2046           tag_tree = proto_item_get_subtree(tag_pi);
2047         }
2048         break;
2049
2050       case ERF_META_TAG_tunneling_mode:
2051         DISSECTOR_ASSERT(tag_info->extra);
2052         {
2053           const int* tunneling_mode_flags[array_length(erf_tunneling_modes)+1];
2054           int i;
2055
2056           /* XXX: This is allowed as the array itself is not constant (not const int* const) */
2057           for (i = 0; i < (int) array_length(erf_tunneling_modes); i++) {
2058             tunneling_mode_flags[i] = &tag_info->extra->hf_values[i];
2059           }
2060           tunneling_mode_flags[array_length(erf_tunneling_modes)] = NULL;
2061
2062           tag_pi = proto_tree_add_bitmask(section_tree, tvb, offset + 4, tag_info->hf_value, tag_info->ett, tunneling_mode_flags, ENC_BIG_ENDIAN);
2063         }
2064         break;
2065
2066       case ERF_META_TAG_ns_dns_ipv4:
2067       case ERF_META_TAG_ns_dns_ipv6:
2068       case ERF_META_TAG_ns_host_ipv4:
2069       case ERF_META_TAG_ns_host_ipv6:
2070       case ERF_META_TAG_ns_host_mac:
2071       case ERF_META_TAG_ns_host_eui:
2072       case ERF_META_TAG_ns_host_wwn:
2073       case ERF_META_TAG_ns_host_ib_gid:
2074       case ERF_META_TAG_ns_host_ib_lid:
2075       case ERF_META_TAG_ns_host_fc_id:
2076       {
2077         int addr_len = ftype_length(tag_ft);
2078
2079         DISSECTOR_ASSERT(tag_info->extra);
2080
2081         tag_tree = proto_tree_add_subtree(section_tree, tvb, offset + 4, taglength, tag_info->ett, &tag_pi, tag_info->tag_template->hfinfo.name);
2082         /* Address */
2083         pi = proto_tree_add_item(tag_tree, tag_info->hf_value, tvb, offset + 4, MIN(addr_len, taglength), IS_FT_INT(tag_ft) || IS_FT_UINT(tag_ft) ? ENC_BIG_ENDIAN : ENC_NA);
2084         /* Name */
2085         proto_tree_add_item(tag_tree, tag_info->extra->hf_values[0], tvb, offset + 4 + addr_len, taglength - addr_len, ENC_UTF_8);
2086         if (pi) {
2087           proto_item_fill_label(PITEM_FINFO(pi), pi_label);
2088           /* Set top level label TagName: Address Hostname */
2089           proto_item_append_text(tag_pi, "%s %s", pi_label /* Includes ": " */,
2090               tvb_get_stringzpad(wmem_packet_scope(), tvb, offset + 4 + addr_len, taglength - addr_len, ENC_UTF_8));
2091         }
2092
2093         break;
2094       }
2095
2096       default:
2097         dissected = FALSE;
2098         break;
2099       }
2100
2101       /* If not special case, dissect generically from template */
2102       if (!dissected) {
2103         if (IS_FT_INT(tag_ft) || IS_FT_UINT(tag_ft)) {
2104           tag_pi = proto_tree_add_item(section_tree, tag_info->hf_value, tvb, offset + 4, taglength, ENC_BIG_ENDIAN);
2105         } else if (IS_FT_STRING(tag_ft)) {
2106           tag_pi = proto_tree_add_item(section_tree, tag_info->hf_value, tvb, offset + 4, taglength, ENC_UTF_8);
2107         } else if (IS_FT_TIME(tag_ft)) {
2108           /*
2109            * ERF timestamps are conveniently the same as NTP/PTP timestamps but
2110            * little endian.
2111            */
2112           /*
2113            * FIXME: ENC_TIME_NTP(_BASE_ZERO) | ENC_LITTLE_ENDIAN only swaps the
2114            * upper and lower 32 bits. Is that a bug or by design? Should add
2115            * a 'PTP" variant that doesn't round to microseconds and use that
2116            * here. For now do by hand.
2117            */
2118           nstime_t t;
2119           guint64 ts;
2120
2121           ts = tvb_get_letoh64(tvb, offset + 4);
2122
2123           t.secs = (long) (ts >> 32);
2124           ts  = ((ts & 0xffffffff) * 1000 * 1000 * 1000);
2125           ts += (ts & 0x80000000) << 1; /* rounding */
2126           t.nsecs = ((int) (ts >> 32));
2127           if (t.nsecs >= 1000000000) {
2128             t.nsecs -= 1000000000;
2129             t.secs += 1;
2130           }
2131
2132           tag_pi = proto_tree_add_time(section_tree, tag_info->hf_value, tvb, offset + 4, taglength, &t);
2133         } else {
2134           tag_pi = proto_tree_add_item(section_tree, tag_info->hf_value, tvb, offset + 4, taglength, ENC_NA);
2135         }
2136       }
2137     }
2138
2139     /* Create subtree for tag if we haven't already */
2140     if (!tag_tree)
2141       tag_tree = proto_item_add_subtree(tag_pi, tag_info->ett);
2142
2143     /* Add tag type field to subtree */
2144     /*
2145      * XXX: Formatting value manually because don't have erf_meta_vs_list
2146      * populated at registration time.
2147      */
2148     proto_tree_add_uint_format_value(tag_tree, hf_erf_meta_tag_type, tvb, offset, 2, tagtype, "%s (%u)", val_to_str(tagtype, VALS(wmem_array_get_raw(erf_meta_index.vs_abbrev_list)), "Unknown"), tagtype);
2149     proto_tree_add_uint(tag_tree, hf_erf_meta_tag_len, tvb, offset + 2, 2, taglength);
2150
2151     offset += ((taglength + 4) + 0x3) & ~0x3;
2152   }
2153
2154   /* Check final section length */
2155   proto_item_set_len(section_pi, offset - sectionoffset);
2156   check_section_length(pinfo, sectionlen_pi, offset, sectionoffset, sectionlen);
2157 }
2158
2159 static int
2160 dissect_erf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2161 {
2162   guint8              flags;
2163   guint8              erf_type;
2164   guint32             atm_hdr  = 0;
2165   proto_tree         *erf_tree;
2166   proto_item         *erf_item;
2167   erf_hdlc_type_vals  hdlc_type;
2168   guint8              first_byte;
2169   tvbuff_t           *new_tvb;
2170   guint8              aal2_cid;
2171   struct atm_phdr     atm_info;
2172
2173   erf_type=pinfo->pseudo_header->erf.phdr.type & 0x7F;
2174
2175   col_set_str(pinfo->cinfo, COL_PROTOCOL, "ERF");
2176
2177   col_add_fstr(pinfo->cinfo, COL_INFO, "%s",
2178        val_to_str(erf_type, erf_type_vals, "Unknown type %u"));
2179
2180   erf_item = proto_tree_add_item(tree, proto_erf, tvb, 0, -1, ENC_NA);
2181   erf_tree = proto_item_add_subtree(erf_item, ett_erf);
2182
2183   dissect_erf_pseudo_header(tvb, pinfo, erf_tree);
2184   if (pinfo->pseudo_header->erf.phdr.type & 0x80) {
2185     dissect_erf_pseudo_extension_header(tvb, pinfo, erf_tree);
2186     }
2187
2188   flags = pinfo->pseudo_header->erf.phdr.flags;
2189   /*
2190    * Set if frame is Received or Sent.
2191    * XXX - this is really testing the low-order bit of the capture
2192    * interface number, so interface 0 is assumed to be capturing
2193    * in one direction on a bi-directional link, interface 1 is
2194    * assumed to be capturing in the other direction on that link,
2195    * and interfaces 2 and 3 are assumed to be capturing in two
2196    * different directions on another link.  We don't distinguish
2197    * between the two links.
2198    */
2199   pinfo->p2p_dir = ( (flags & 0x01) ? P2P_DIR_RECV : P2P_DIR_SENT);
2200
2201   switch (erf_type) {
2202
2203   case ERF_TYPE_RAW_LINK:
2204     if(sdh_handle) {
2205       call_dissector(sdh_handle, tvb, pinfo, tree);
2206     }
2207     else{
2208       call_data_dissector(tvb, pinfo, tree);
2209     }
2210     break;
2211
2212   case ERF_TYPE_ETH:
2213   case ERF_TYPE_COLOR_ETH:
2214   case ERF_TYPE_DSM_COLOR_ETH:
2215     dissect_eth_header(tvb, pinfo, erf_tree);
2216     /* fall through */
2217   case ERF_TYPE_IPV4:
2218   case ERF_TYPE_IPV6:
2219   case ERF_TYPE_INFINIBAND:
2220   case ERF_TYPE_INFINIBAND_LINK:
2221     if (!dissector_try_uint(erf_dissector_table, erf_type, tvb, pinfo, tree)) {
2222       call_data_dissector(tvb, pinfo, tree);
2223     }
2224     break;
2225
2226   case ERF_TYPE_LEGACY:
2227   case ERF_TYPE_IP_COUNTER:
2228   case ERF_TYPE_TCP_FLOW_COUNTER:
2229     /* undefined */
2230     break;
2231
2232   case ERF_TYPE_PAD:
2233     /* Nothing to do */
2234     break;
2235
2236   case ERF_TYPE_MC_RAW:
2237     dissect_mc_raw_header(tvb, pinfo, erf_tree);
2238     call_data_dissector(tvb, pinfo, tree);
2239     break;
2240
2241   case ERF_TYPE_MC_RAW_CHANNEL:
2242     dissect_mc_rawlink_header(tvb, pinfo, erf_tree);
2243     call_data_dissector(tvb, pinfo, tree);
2244     break;
2245
2246   case ERF_TYPE_MC_ATM:
2247     dissect_mc_atm_header(tvb, pinfo, erf_tree);
2248     /* continue with type ATM */
2249
2250   case ERF_TYPE_ATM:
2251     memset(&atm_info, 0, sizeof(atm_info));
2252     atm_hdr = tvb_get_ntohl(tvb, 0);
2253     atm_info.vpi = ((atm_hdr & 0x0ff00000) >> 20);
2254     atm_info.vci = ((atm_hdr & 0x000ffff0) >>  4);
2255     atm_info.channel = (flags & 0x03);
2256
2257     /* Work around to have decoding working */
2258     if (erf_rawcell_first) {
2259       new_tvb = tvb_new_subset_remaining(tvb, ATM_HDR_LENGTH);
2260       /* Treat this as a (short) ATM AAL5 PDU */
2261       atm_info.aal = AAL_5;
2262       switch (erf_aal5_type) {
2263
2264       case ERF_AAL5_GUESS:
2265         atm_info.type = TRAF_UNKNOWN;
2266         atm_info.subtype = TRAF_ST_UNKNOWN;
2267         /* Try to guess the type according to the first bytes */
2268         erf_atm_guess_traffic_type(new_tvb, 0, tvb_captured_length(new_tvb), &atm_info);
2269         break;
2270
2271       case ERF_AAL5_LLC:
2272         atm_info.type = TRAF_LLCMX;
2273         atm_info.subtype = TRAF_ST_UNKNOWN;
2274         break;
2275
2276       case ERF_AAL5_UNSPEC:
2277         atm_info.aal = AAL_5;
2278         atm_info.type = TRAF_UNKNOWN;
2279         atm_info.subtype = TRAF_ST_UNKNOWN;
2280         break;
2281       }
2282
2283       call_dissector_with_data(atm_untruncated_handle, new_tvb, pinfo, tree,
2284                                &atm_info);
2285     } else {
2286       /* Treat this as a raw cell */
2287       atm_info.flags |= ATM_RAW_CELL;
2288       atm_info.flags |= ATM_NO_HEC;
2289       atm_info.aal = AAL_UNKNOWN;
2290       /* can call atm_untruncated because we set ATM_RAW_CELL flag */
2291       call_dissector_with_data(atm_untruncated_handle, tvb, pinfo, tree,
2292                                &atm_info);
2293     }
2294     break;
2295
2296   case ERF_TYPE_MC_AAL5:
2297     dissect_mc_aal5_header(tvb, pinfo, erf_tree);
2298     /* continue with type AAL5 */
2299
2300   case ERF_TYPE_AAL5:
2301     atm_hdr = tvb_get_ntohl(tvb, 0);
2302     memset(&atm_info, 0, sizeof(atm_info));
2303     atm_info.vpi = ((atm_hdr & 0x0ff00000) >> 20);
2304     atm_info.vci = ((atm_hdr & 0x000ffff0) >>  4);
2305     atm_info.channel = (flags & 0x03);
2306
2307     new_tvb = tvb_new_subset_remaining(tvb, ATM_HDR_LENGTH);
2308     /* Work around to have decoding working */
2309     atm_info.aal = AAL_5;
2310     switch (erf_aal5_type) {
2311
2312     case ERF_AAL5_GUESS:
2313       atm_info.type = TRAF_UNKNOWN;
2314       atm_info.subtype = TRAF_ST_UNKNOWN;
2315       /* Try to guess the type according to the first bytes */
2316       erf_atm_guess_traffic_type(new_tvb, 0, tvb_captured_length(new_tvb), &atm_info);
2317       break;
2318
2319     case ERF_AAL5_LLC:
2320       atm_info.type = TRAF_LLCMX;
2321       atm_info.subtype = TRAF_ST_UNKNOWN;
2322       break;
2323
2324     case ERF_AAL5_UNSPEC:
2325       atm_info.aal = AAL_5;
2326       atm_info.type = TRAF_UNKNOWN;
2327       atm_info.subtype = TRAF_ST_UNKNOWN;
2328       break;
2329     }
2330
2331     call_dissector_with_data(atm_untruncated_handle, new_tvb, pinfo, tree,
2332                              &atm_info);
2333     break;
2334
2335   case ERF_TYPE_MC_AAL2:
2336     dissect_mc_aal2_header(tvb, pinfo, erf_tree);
2337
2338     /*
2339      * Most of the information is in the ATM header; fetch it.
2340      */
2341     atm_hdr = tvb_get_ntohl(tvb, 0);
2342
2343     /*
2344      * The channel identification number is in the MC header, so it's
2345      * in the pseudo-header, not in the packet data.
2346      */
2347     aal2_cid = (pinfo->pseudo_header->erf.subhdr.mc_hdr & MC_AAL2_CID_MASK) >> MC_AAL2_CID_SHIFT;
2348
2349     /* Zero out and fill in the ATM pseudo-header. */
2350     memset(&atm_info, 0, sizeof(atm_info));
2351     atm_info.aal = AAL_2;
2352     atm_info.flags |= ATM_AAL2_NOPHDR;
2353     atm_info.vpi = ((atm_hdr & 0x0ff00000) >> 20);
2354     atm_info.vci = ((atm_hdr & 0x000ffff0) >>  4);
2355     atm_info.channel = (flags & 0x03);
2356     atm_info.aal2_cid = aal2_cid;
2357     atm_info.type = TRAF_UNKNOWN;
2358     atm_info.subtype = TRAF_ST_UNKNOWN;
2359
2360     /* remove ATM cell header from tvb */
2361     new_tvb = tvb_new_subset_remaining(tvb, ATM_HDR_LENGTH);
2362     call_dissector_with_data(atm_untruncated_handle, new_tvb, pinfo, tree,
2363                              &atm_info);
2364     break;
2365
2366   case ERF_TYPE_AAL2:
2367     dissect_aal2_header(tvb, pinfo, erf_tree);
2368
2369     /*
2370      * Most of the information is in the ATM header; fetch it.
2371      */
2372     atm_hdr = tvb_get_ntohl(tvb, 0);
2373
2374     /*
2375      * The channel identification number is in the AAL2 header, so it's
2376      * in the pseudo-header, not in the packet data.
2377      */
2378     aal2_cid = (pinfo->pseudo_header->erf.subhdr.aal2_hdr & AAL2_CID_MASK) >> AAL2_CID_SHIFT;
2379
2380     /* Zero out and fill in the ATM pseudo-header. */
2381     memset(&atm_info, 0, sizeof(atm_info));
2382     atm_info.aal = AAL_2;
2383     atm_info.flags |= ATM_AAL2_NOPHDR;
2384     atm_info.vpi = ((atm_hdr & 0x0ff00000) >> 20);
2385     atm_info.vci = ((atm_hdr & 0x000ffff0) >>  4);
2386     atm_info.channel = (flags & 0x03);
2387     atm_info.aal2_cid = aal2_cid;
2388     atm_info.type = TRAF_UNKNOWN;
2389     atm_info.subtype = TRAF_ST_UNKNOWN;
2390
2391     /* remove ATM cell header from tvb */
2392     new_tvb = tvb_new_subset_remaining(tvb, ATM_HDR_LENGTH);
2393     call_dissector_with_data(atm_untruncated_handle, new_tvb, pinfo, tree,
2394                              &atm_info);
2395     break;
2396
2397   case ERF_TYPE_MC_HDLC:
2398     dissect_mc_hdlc_header(tvb, pinfo, erf_tree);
2399     /* continue with type HDLC */
2400
2401   case ERF_TYPE_HDLC_POS:
2402   case ERF_TYPE_COLOR_HDLC_POS:
2403   case ERF_TYPE_DSM_COLOR_HDLC_POS:
2404   case ERF_TYPE_COLOR_MC_HDLC_POS:
2405     hdlc_type = (erf_hdlc_type_vals)erf_hdlc_type;
2406
2407     if (hdlc_type == ERF_HDLC_GUESS) {
2408       /* Try to guess the type. */
2409       first_byte = tvb_get_guint8(tvb, 0);
2410       if (first_byte == 0x0f || first_byte == 0x8f)
2411         hdlc_type = ERF_HDLC_CHDLC;
2412       else {
2413         /* Anything to check for to recognize Frame Relay or MTP2?
2414            Should we require PPP packets to begin with FF 03? */
2415         hdlc_type = ERF_HDLC_PPP;
2416       }
2417     }
2418     /* Clean the pseudo header (if used in subdissector) and call the
2419        appropriate subdissector. */
2420     switch (hdlc_type) {
2421     case ERF_HDLC_CHDLC:
2422       call_dissector(chdlc_handle, tvb, pinfo, tree);
2423       break;
2424     case ERF_HDLC_PPP:
2425       call_dissector(ppp_handle, tvb, pinfo, tree);
2426       break;
2427     case ERF_HDLC_FRELAY:
2428       memset(&pinfo->pseudo_header->x25, 0, sizeof(pinfo->pseudo_header->x25));
2429       call_dissector(frelay_handle, tvb, pinfo, tree);
2430       break;
2431     case ERF_HDLC_MTP2:
2432       /* not used, but .. */
2433       memset(&pinfo->pseudo_header->mtp2, 0, sizeof(pinfo->pseudo_header->mtp2));
2434       call_dissector(mtp2_handle, tvb, pinfo, tree);
2435       break;
2436     default:
2437       break;
2438     }
2439     break;
2440
2441   case ERF_TYPE_META:
2442     dissect_meta_record_tags(tvb, pinfo, erf_tree);
2443     break;
2444
2445   default:
2446     break;
2447   } /* erf type */
2448   return tvb_captured_length(tvb);
2449 }
2450
2451 static void erf_init_dissection(void)
2452 {
2453   erf_state.implicit_host_id = 0;
2454   erf_state.source_map = wmem_map_new(wmem_file_scope(), wmem_int64_hash, g_int64_equal);
2455   /* Old map is freed automatically */
2456 }
2457
2458 void
2459 proto_register_erf(void)
2460 {
2461
2462   static hf_register_info hf[] = {
2463     /* ERF Header */
2464     { &hf_erf_ts,
2465       { "Timestamp", "erf.ts",
2466         FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL } },
2467     { &hf_erf_rectype,
2468       { "Record type", "erf.types",
2469         FT_UINT8, BASE_HEX,  NULL, 0x0, NULL, HFILL } },
2470     { &hf_erf_type,
2471       { "Type", "erf.types.type",
2472         FT_UINT8, BASE_DEC,  VALS(erf_type_vals), ERF_HDR_TYPE_MASK, NULL, HFILL } },
2473     { &hf_erf_ehdr,
2474       { "Extension header present", "erf.types.ext_header",
2475         FT_UINT8, BASE_DEC,  NULL, ERF_HDR_EHDR_MASK, NULL, HFILL } },
2476     { &hf_erf_flags,
2477       { "Flags", "erf.flags",
2478         FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
2479     { &hf_erf_flags_cap,
2480       { "Capture interface", "erf.flags.cap",
2481         FT_UINT8, BASE_DEC, NULL, ERF_HDR_CAP_MASK, NULL, HFILL } },
2482     { &hf_erf_flags_vlen,
2483       { "Varying record length", "erf.flags.vlen",
2484         FT_UINT8, BASE_DEC, NULL, ERF_HDR_VLEN_MASK, NULL, HFILL } },
2485     { &hf_erf_flags_trunc,
2486       { "Truncated", "erf.flags.trunc",
2487         FT_UINT8, BASE_DEC, NULL, ERF_HDR_TRUNC_MASK, NULL, HFILL } },
2488     { &hf_erf_flags_rxe,
2489       { "RX error", "erf.flags.rxe",
2490         FT_UINT8, BASE_DEC, NULL, ERF_HDR_RXE_MASK, NULL, HFILL } },
2491     { &hf_erf_flags_dse,
2492       { "DS error", "erf.flags.dse",
2493         FT_UINT8, BASE_DEC, NULL, ERF_HDR_DSE_MASK, NULL, HFILL } },
2494     { &hf_erf_flags_res,
2495        { "Reserved", "erf.flags.res",
2496          FT_UINT8, BASE_HEX, NULL, ERF_HDR_RES_MASK, NULL, HFILL } },
2497      { &hf_erf_rlen,
2498        { "Record length", "erf.rlen",
2499          FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
2500      { &hf_erf_lctr,
2501        { "Loss counter", "erf.lctr",
2502          FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
2503      { &hf_erf_wlen,
2504        { "Wire length", "erf.wlen",
2505          FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
2506     { &hf_erf_ehdr_t,
2507       { "Extension Header", "erf.ehdr.types",
2508         FT_UINT8, BASE_DEC, VALS(ehdr_type_vals), 0x0, NULL, HFILL } },
2509
2510     /* Intercept ID Extension Header */
2511     { &hf_erf_ehdr_int_res1,
2512       { "Reserved", "erf.ehdr.int.res1",
2513         FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
2514     { &hf_erf_ehdr_int_id,
2515       { "Intercept ID", "erf.ehdr.int.intid",
2516         FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
2517     { &hf_erf_ehdr_int_res2,
2518       { "Reserved", "erf.ehdr.int.res2",
2519         FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
2520
2521     /* Raw Link Extension Header */
2522     { &hf_erf_ehdr_raw_link_res,
2523       { "Reserved", "erf.ehdr.raw.res",
2524         FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
2525     { &hf_erf_ehdr_raw_link_seqnum,
2526       { "Sequence number", "erf.ehdr.raw.seqnum",
2527         FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
2528     { &hf_erf_ehdr_raw_link_rate,
2529       { "Rate", "erf.ehdr.raw.rate",
2530         FT_UINT8, BASE_DEC, VALS(raw_link_rates), 0x0, NULL, HFILL } },
2531     { &hf_erf_ehdr_raw_link_type,
2532       { "Link Type", "erf.ehdr.raw.link_type",
2533         FT_UINT8, BASE_DEC, VALS(raw_link_types), 0x0, NULL, HFILL } },
2534
2535     /* Classification Extension Header */
2536     { &hf_erf_ehdr_class_flags,
2537       { "Flags", "erf.ehdr.class.flags",
2538         FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
2539     { &hf_erf_ehdr_class_flags_sh,
2540       { "Search hit", "erf.ehdr.class.flags.sh",
2541         FT_UINT32, BASE_DEC, NULL, EHDR_CLASS_SH_MASK, NULL, HFILL } },
2542     { &hf_erf_ehdr_class_flags_shm,
2543       { "Multiple search hits", "erf.ehdr.class.flags.shm",
2544         FT_UINT32, BASE_DEC, NULL, EHDR_CLASS_SHM_MASK, NULL, HFILL } },
2545     { &hf_erf_ehdr_class_flags_res1,
2546       { "Reserved", "erf.ehdr.class.flags.res1",
2547         FT_UINT32, BASE_HEX, NULL, EHDR_CLASS_RES1_MASK, NULL, HFILL } },
2548     { &hf_erf_ehdr_class_flags_user,
2549       { "User classification", "erf.ehdr.class.flags.user",
2550         FT_UINT32, BASE_DEC, NULL, EHDR_CLASS_USER_MASK, NULL, HFILL } },
2551     { &hf_erf_ehdr_class_flags_res2,
2552       { "Reserved", "erf.ehdr.class.flags.res2",
2553         FT_UINT32, BASE_HEX, NULL, EHDR_CLASS_RES2_MASK, NULL, HFILL } },
2554     { &hf_erf_ehdr_class_flags_drop,
2555       { "Drop Steering Bit", "erf.ehdr.class.flags.drop",
2556         FT_UINT32, BASE_DEC, NULL, EHDR_CLASS_DROP_MASK, NULL, HFILL } },
2557     { &hf_erf_ehdr_class_flags_str,
2558       { "Stream Steering Bits", "erf.ehdr.class.flags.str",
2559         FT_UINT32, BASE_DEC, NULL, EHDR_CLASS_STER_MASK, NULL, HFILL } },
2560     { &hf_erf_ehdr_class_seqnum,
2561       { "Sequence number", "erf.ehdr.class.seqnum",
2562         FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
2563
2564     /* BFS Extension Header */
2565     { &hf_erf_ehdr_bfs_hash,
2566       { "Hash", "erf.ehdr.bfs.hash",
2567         FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } },
2568     { &hf_erf_ehdr_bfs_color,
2569       { "Filter Color", "erf.ehdr.bfs.color",
2570         FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } },
2571     { &hf_erf_ehdr_bfs_raw_hash,
2572       { "Raw Hash", "erf.ehdr.bfs.rawhash",
2573         FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } },
2574
2575     /* Channelised Extension Header */
2576     { &hf_erf_ehdr_chan_morebits,
2577       { "More Bits", "erf.ehdr.chan.morebits",
2578         FT_BOOLEAN, BASE_NONE, NULL, 0, NULL, HFILL } },
2579     { &hf_erf_ehdr_chan_morefrag,
2580       { "More Fragments", "erf.ehdr.chan.morefrag",
2581         FT_BOOLEAN, BASE_NONE, NULL, 0, NULL, HFILL } },
2582     { &hf_erf_ehdr_chan_seqnum,
2583       { "Sequence Number", "erf.ehdr.chan.seqnum",
2584         FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
2585     { &hf_erf_ehdr_chan_res,
2586       { "Reserved", "erf.ehdr.chan.res",
2587         FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } },
2588     { &hf_erf_ehdr_chan_virt_container_id,
2589       { "Virtual Container ID", "erf.ehdr.chan.vcid",
2590         FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } },
2591     { &hf_erf_ehdr_chan_assoc_virt_container_size,
2592       { "Associated Virtual Container Size", "erf.ehdr.chan.vcsize",
2593         FT_UINT8, BASE_HEX, VALS(channelised_assoc_virt_container_size), 0, NULL, HFILL } },
2594     { &hf_erf_ehdr_chan_rate,
2595       { "Origin Line Type/Rate", "erf.ehdr.chan.rate",
2596         FT_UINT8, BASE_HEX, VALS(channelised_rate), 0, NULL, HFILL } },
2597     { &hf_erf_ehdr_chan_type,
2598       { "Frame Part Type", "erf.ehdr.chan.type",
2599         FT_UINT8, BASE_HEX, VALS(channelised_type), 0, NULL, HFILL } },
2600
2601     /* Signature Extension Header */
2602     { &hf_erf_ehdr_signature_payload_hash,
2603       { "Payload Hash", "erf.ehdr.signature.payloadhash",
2604         FT_UINT24, BASE_HEX, NULL, 0, NULL, HFILL } },
2605     { &hf_erf_ehdr_signature_color,
2606       { "Filter Color", "erf.ehdr.signature.color",
2607         FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } },
2608     { &hf_erf_ehdr_signature_flow_hash,
2609       { "Flow Hash", "erf.ehdr.signature.flowhash",
2610         FT_UINT24, BASE_HEX, NULL, 0, NULL, HFILL } },
2611
2612     /* Flow ID Extension Header */
2613     { &hf_erf_ehdr_flow_id_source_id,
2614       { "Source ID", "erf.ehdr.flowid.sourceid",
2615         FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } },
2616     { &hf_erf_ehdr_flow_id_hash_type,
2617       { "Hash Type", "erf.ehdr.flowid.hashtype",
2618         FT_UINT8, BASE_HEX, VALS(erf_hash_type), 0, NULL, HFILL } },
2619     { &hf_erf_ehdr_flow_id_stack_type,
2620       { "Stack Type", "erf.ehdr.flowid.stacktype",
2621         FT_UINT8, BASE_HEX, VALS(erf_stack_type), 0, NULL, HFILL } },
2622     { &hf_erf_ehdr_flow_id_flow_hash,
2623       { "Flow Hash", "erf.ehdr.flowid.flowhash",
2624         FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } },
2625
2626     /* Host ID Extension Header */
2627     { &hf_erf_ehdr_host_id_sourceid,
2628       { "Source ID", "erf.ehdr.hostid.sourceid",
2629         FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } },
2630     { &hf_erf_ehdr_host_id_hostid,
2631       { "Host ID", "erf.ehdr.hostid.hostid",
2632         FT_UINT48, BASE_HEX, NULL, 0, NULL, HFILL } },
2633
2634     /* Generated fields for navigating Host ID/Source ID */
2635     { &hf_erf_sourceid,
2636       { "Source ID", "erf.sourceid",
2637         FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } },
2638     { &hf_erf_hostid,
2639       { "Host ID", "erf.hostid",
2640         FT_UINT48, BASE_HEX, NULL, 0, NULL, HFILL } },
2641     { &hf_erf_source_current,
2642       { "Next Metadata in Source", "erf.source_meta_frame_current",
2643         FT_FRAMENUM, BASE_NONE, NULL, 0, NULL, HFILL } },
2644     { &hf_erf_source_next,
2645       { "Next Metadata in Source", "erf.source_meta_frame_next",
2646         FT_FRAMENUM, BASE_NONE, NULL, 0, NULL, HFILL } },
2647     { &hf_erf_source_prev,
2648       { "Previous Metadata in Source", "erf.source_meta_frame_prev",
2649         FT_FRAMENUM, BASE_NONE, NULL, 0, NULL, HFILL } },
2650
2651     /* Unknown Extension Header */
2652     { &hf_erf_ehdr_unk,
2653       { "Data", "erf.ehdr.unknown.data",
2654         FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL } },
2655
2656     /* MC HDLC Header */
2657     { &hf_erf_mc_hdlc,
2658       { "Multi Channel HDLC Header", "erf.mchdlc",
2659         FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
2660     { &hf_erf_mc_hdlc_cn,
2661       { "Connection number", "erf.mchdlc.cn",
2662         FT_UINT32, BASE_DEC, NULL, MC_HDLC_CN_MASK, NULL, HFILL } },
2663     { &hf_erf_mc_hdlc_res1,
2664       { "Reserved", "erf.mchdlc.res1",
2665         FT_UINT32, BASE_HEX, NULL, MC_HDLC_RES1_MASK, NULL, HFILL } },
2666     { &hf_erf_mc_hdlc_res2,
2667       { "Reserved", "erf.mchdlc.res2",
2668         FT_UINT32, BASE_HEX, NULL, MC_HDLC_RES2_MASK, NULL, HFILL } },
2669     { &hf_erf_mc_hdlc_fcse,
2670       { "FCS error", "erf.mchdlc.fcse",
2671         FT_UINT32, BASE_DEC, NULL, MC_HDLC_FCSE_MASK, NULL, HFILL } },
2672     { &hf_erf_mc_hdlc_sre,
2673       { "Short record error", "erf.mchdlc.sre",
2674         FT_UINT32, BASE_DEC, NULL, MC_HDLC_SRE_MASK, NULL, HFILL } },
2675     { &hf_erf_mc_hdlc_lre,
2676       { "Long record error", "erf.mchdlc.lre",
2677         FT_UINT32, BASE_DEC, NULL, MC_HDLC_LRE_MASK, NULL, HFILL } },
2678     { &hf_erf_mc_hdlc_afe,
2679       { "Aborted frame error", "erf.mchdlc.afe",
2680         FT_UINT32, BASE_DEC, NULL, MC_HDLC_AFE_MASK, NULL, HFILL } },
2681     { &hf_erf_mc_hdlc_oe,
2682       { "Octet error", "erf.mchdlc.oe",
2683         FT_UINT32, BASE_DEC, NULL, MC_HDLC_OE_MASK, NULL, HFILL } },
2684     { &hf_erf_mc_hdlc_lbe,
2685       { "Lost byte error", "erf.mchdlc.lbe",
2686         FT_UINT32, BASE_DEC, NULL, MC_HDLC_LBE_MASK, NULL, HFILL } },
2687     { &hf_erf_mc_hdlc_first,
2688       { "First record", "erf.mchdlc.first",
2689         FT_UINT32, BASE_DEC, NULL, MC_HDLC_FIRST_MASK, NULL, HFILL } },
2690     { &hf_erf_mc_hdlc_res3,
2691       { "Reserved", "erf.mchdlc.res3",
2692         FT_UINT32, BASE_HEX, NULL, MC_HDLC_RES3_MASK, NULL, HFILL } },
2693
2694     /* MC RAW Header */
2695     { &hf_erf_mc_raw,
2696       { "Multi Channel RAW Header", "erf.mcraw",
2697         FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
2698     { &hf_erf_mc_raw_int,
2699       { "Physical interface", "erf.mcraw.int",
2700         FT_UINT32, BASE_DEC, NULL, MC_RAW_INT_MASK, NULL, HFILL } },
2701     { &hf_erf_mc_raw_res1,
2702       { "Reserved", "erf.mcraw.res1",
2703         FT_UINT32, BASE_HEX, NULL, MC_RAW_RES1_MASK, NULL, HFILL } },
2704     { &hf_erf_mc_raw_sre,
2705       { "Short record error", "erf.mcraw.sre",
2706         FT_UINT32, BASE_DEC, NULL, MC_RAW_SRE_MASK, NULL, HFILL } },
2707     { &hf_erf_mc_raw_lre,
2708       { "Long record error", "erf.mcraw.lre",
2709         FT_UINT32, BASE_DEC, NULL, MC_RAW_LRE_MASK, NULL, HFILL } },
2710     { &hf_erf_mc_raw_res2,
2711       { "Reserved", "erf.mcraw.res2",
2712         FT_UINT32, BASE_HEX, NULL, MC_RAW_RES2_MASK, NULL, HFILL } },
2713     { &hf_erf_mc_raw_lbe,
2714       { "Lost byte error", "erf.mcraw.lbe",
2715         FT_UINT32, BASE_DEC, NULL, MC_RAW_LBE_MASK, NULL, HFILL } },
2716     { &hf_erf_mc_raw_first,
2717       { "First record", "erf.mcraw.first",
2718         FT_UINT32, BASE_DEC, NULL, MC_RAW_FIRST_MASK, NULL, HFILL } },
2719     { &hf_erf_mc_raw_res3,
2720       { "Reserved", "erf.mcraw.res3",
2721         FT_UINT32, BASE_HEX, NULL, MC_RAW_RES3_MASK, NULL, HFILL } },
2722
2723     /* MC ATM Header */
2724     { &hf_erf_mc_atm,
2725       { "Multi Channel ATM Header", "erf.mcatm",
2726         FT_UINT32, BASE_HEX, NULL, 0x00, NULL, HFILL } },
2727     { &hf_erf_mc_atm_cn,
2728       { "Connection number", "erf.mcatm.cn",
2729         FT_UINT32, BASE_DEC, NULL, MC_ATM_CN_MASK, NULL, HFILL } },
2730     { &hf_erf_mc_atm_res1,
2731       { "Reserved", "erf.mcatm.res1",
2732         FT_UINT32, BASE_HEX, NULL, MC_ATM_RES1_MASK, NULL, HFILL } },
2733     { &hf_erf_mc_atm_mul,
2734       { "Multiplexed", "erf.mcatm.mul",
2735         FT_UINT32, BASE_DEC, NULL, MC_ATM_MUL_MASK, NULL, HFILL } },
2736     { &hf_erf_mc_atm_port,
2737       { "Physical port", "erf.mcatm.port",
2738         FT_UINT32, BASE_DEC, NULL, MC_ATM_PORT_MASK, NULL, HFILL } },
2739     { &hf_erf_mc_atm_res2,
2740       { "Reserved", "erf.mcatm.res2",
2741         FT_UINT32, BASE_HEX, NULL, MC_ATM_RES2_MASK, NULL, HFILL } },
2742     { &hf_erf_mc_atm_lbe,
2743       { "Lost Byte Error", "erf.mcatm.lbe",
2744         FT_UINT32, BASE_DEC, NULL, MC_ATM_LBE_MASK, NULL, HFILL } },
2745     { &hf_erf_mc_atm_hec,
2746       { "HEC corrected", "erf.mcatm.hec",
2747         FT_UINT32, BASE_DEC, NULL, MC_ATM_HEC_MASK, NULL, HFILL } },
2748     { &hf_erf_mc_atm_crc10,
2749       { "OAM Cell CRC10 Error (not implemented)", "erf.mcatm.crc10",
2750         FT_UINT32, BASE_DEC, NULL, MC_ATM_CRC10_MASK, NULL, HFILL } },
2751     { &hf_erf_mc_atm_oamcell,
2752       { "OAM Cell", "erf.mcatm.oamcell",
2753         FT_UINT32, BASE_DEC, NULL, MC_ATM_OAMCELL_MASK, NULL, HFILL } },
2754     { &hf_erf_mc_atm_first,
2755       { "First record", "erf.mcatm.first",
2756         FT_UINT32, BASE_DEC, NULL, MC_ATM_FIRST_MASK, NULL, HFILL } },
2757     { &hf_erf_mc_atm_res3,
2758       { "Reserved", "erf.mcatm.res3",
2759         FT_UINT32, BASE_HEX, NULL, MC_ATM_RES3_MASK, NULL, HFILL } },
2760
2761     /* MC RAW Link Header */
2762     { &hf_erf_mc_rawl,
2763       { "Multi Channel RAW Link Header", "erf.mcrawl",
2764         FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
2765     { &hf_erf_mc_rawl_cn,
2766       { "Connection number", "erf.mcrawl.cn",
2767         FT_UINT32, BASE_DEC, NULL, MC_RAWL_CN_MASK, NULL, HFILL } },
2768     { &hf_erf_mc_rawl_res1,
2769       { "Reserved", "erf.mcrawl.res1",
2770         FT_UINT32, BASE_HEX, NULL, MC_RAWL_RES2_MASK, NULL, HFILL } },
2771     { &hf_erf_mc_rawl_lbe,
2772       { "Lost byte error", "erf.mcrawl.lbe",
2773         FT_UINT32, BASE_DEC, NULL, MC_RAWL_LBE_MASK, NULL, HFILL } },
2774     { &hf_erf_mc_rawl_first,
2775       { "First record", "erf.mcrawl.first",
2776         FT_UINT32, BASE_DEC, NULL, MC_RAWL_FIRST_MASK, NULL, HFILL } },
2777     { &hf_erf_mc_rawl_res2,
2778       { "Reserved", "erf.mcrawl.res2",
2779         FT_UINT32, BASE_HEX, NULL, MC_RAWL_RES2_MASK, NULL, HFILL } },
2780
2781     /* MC AAL5 Header */
2782     { &hf_erf_mc_aal5,
2783       { "Multi Channel AAL5 Header", "erf.mcaal5",
2784         FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
2785     { &hf_erf_mc_aal5_cn,
2786       { "Connection number", "erf.mcaal5.cn",
2787         FT_UINT32, BASE_DEC, NULL, MC_AAL5_CN_MASK, NULL, HFILL } },
2788     { &hf_erf_mc_aal5_res1,
2789       { "Reserved", "erf.mcaal5.res1",
2790         FT_UINT32, BASE_HEX, NULL, MC_AAL5_RES1_MASK, NULL, HFILL } },
2791     { &hf_erf_mc_aal5_port,
2792       { "Physical port", "erf.mcaal5.port",
2793         FT_UINT32, BASE_DEC, NULL, MC_AAL5_PORT_MASK, NULL, HFILL } },
2794     { &hf_erf_mc_aal5_crcck,
2795       { "CRC checked", "erf.mcaal5.crcck",
2796         FT_UINT32, BASE_DEC, NULL, MC_AAL5_CRCCK_MASK, NULL, HFILL } },
2797     { &hf_erf_mc_aal5_crce,
2798       { "CRC error", "erf.mcaal5.crce",
2799         FT_UINT32, BASE_DEC, NULL, MC_AAL5_CRCE_MASK, NULL, HFILL } },
2800     { &hf_erf_mc_aal5_lenck,
2801       { "Length checked", "erf.mcaal5.lenck",
2802         FT_UINT32, BASE_DEC, NULL, MC_AAL5_LENCK_MASK, NULL, HFILL } },
2803     { &hf_erf_mc_aal5_lene,
2804       { "Length error", "erf.mcaal5.lene",
2805         FT_UINT32, BASE_DEC, NULL, MC_AAL5_LENE_MASK, NULL, HFILL } },
2806     { &hf_erf_mc_aal5_res2,
2807       { "Reserved", "erf.mcaal5.res2",
2808         FT_UINT32, BASE_HEX, NULL, MC_AAL5_RES2_MASK, NULL, HFILL } },
2809     { &hf_erf_mc_aal5_first,
2810       { "First record", "erf.mcaal5.first",
2811         FT_UINT32, BASE_DEC, NULL, MC_AAL5_FIRST_MASK, NULL, HFILL } },
2812     { &hf_erf_mc_aal5_res3,
2813       { "Reserved", "erf.mcaal5.res3",
2814         FT_UINT32, BASE_HEX, NULL, MC_AAL5_RES3_MASK, NULL, HFILL } },
2815
2816     /* MC AAL2 Header */
2817     { &hf_erf_mc_aal2,
2818       { "Multi Channel AAL2 Header", "erf.mcaal2",
2819         FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
2820     { &hf_erf_mc_aal2_cn,
2821       { "Connection number", "erf.mcaal2.cn",
2822         FT_UINT32, BASE_DEC, NULL, MC_AAL2_CN_MASK, NULL, HFILL } },
2823     { &hf_erf_mc_aal2_res1,
2824       { "Reserved for extra connection", "erf.mcaal2.res1",
2825         FT_UINT32, BASE_HEX, NULL, MC_AAL2_RES1_MASK, NULL, HFILL } },
2826     { &hf_erf_mc_aal2_res2,
2827       { "Reserved for type", "erf.mcaal2.mul",
2828         FT_UINT32, BASE_HEX, NULL, MC_AAL2_RES2_MASK, NULL, HFILL } },
2829     { &hf_erf_mc_aal2_port,
2830       { "Physical port", "erf.mcaal2.port",
2831         FT_UINT32, BASE_DEC, NULL, MC_AAL2_PORT_MASK, NULL, HFILL } },
2832     { &hf_erf_mc_aal2_res3,
2833       { "Reserved", "erf.mcaal2.res2",
2834         FT_UINT32, BASE_HEX, NULL, MC_AAL2_RES3_MASK, NULL, HFILL } },
2835     { &hf_erf_mc_aal2_first,
2836       { "First cell received", "erf.mcaal2.lbe",
2837         FT_UINT32, BASE_DEC, NULL, MC_AAL2_FIRST_MASK, NULL, HFILL } },
2838     { &hf_erf_mc_aal2_maale,
2839       { "MAAL error", "erf.mcaal2.hec",
2840         FT_UINT32, BASE_DEC, NULL, MC_AAL2_MAALE_MASK, NULL, HFILL } },
2841     { &hf_erf_mc_aal2_lene,
2842       { "Length error", "erf.mcaal2.crc10",
2843         FT_UINT32, BASE_DEC, NULL, MC_AAL2_LENE_MASK, NULL, HFILL } },
2844     { &hf_erf_mc_aal2_cid,
2845       { "Channel Identification Number", "erf.mcaal2.cid",
2846         FT_UINT32, BASE_DEC, NULL, MC_AAL2_CID_MASK, NULL, HFILL } },
2847
2848     /* AAL2 Header */
2849     { &hf_erf_aal2,
2850       { "AAL2 Header", "erf.aal2",
2851         FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
2852     { &hf_erf_aal2_cid,
2853       { "Channel Identification Number", "erf.aal2.cid",
2854         FT_UINT32, BASE_DEC, NULL, AAL2_CID_MASK, NULL, HFILL } },
2855     { &hf_erf_aal2_maale,
2856       { "MAAL error number", "erf.aal2.maale",
2857         FT_UINT32, BASE_DEC, NULL, AAL2_MAALE_MASK, NULL, HFILL } },
2858     { &hf_erf_aal2_maalei,
2859       { "MAAL error", "erf.aal2.hec",
2860         FT_UINT32, BASE_DEC, NULL, AAL2_MAALEI_MASK, NULL, HFILL } },
2861     { &hf_erf_aal2_first,
2862       { "First cell received", "erf.aal2.lbe",
2863         FT_UINT32, BASE_DEC, NULL, AAL2_FIRST_MASK, NULL, HFILL } },
2864     { &hf_erf_aal2_res1,
2865       { "Reserved", "erf.aal2.res1",
2866         FT_UINT32, BASE_HEX, NULL, AAL2_RES1_MASK, NULL, HFILL } },
2867
2868     /* ETH Header */
2869     { &hf_erf_eth,
2870       { "Ethernet pad", "erf.eth",
2871         FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
2872     { &hf_erf_eth_off,
2873       { "Offset", "erf.eth.off",
2874         FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } },
2875     { &hf_erf_eth_pad,
2876       { "Padding", "erf.eth.pad",
2877         FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
2878
2879     /* MetaERF record unknown tags */
2880     { &hf_erf_meta_tag_type,
2881       { "Tag Type", "erf.meta.tag.type",
2882         FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
2883     { &hf_erf_meta_tag_len,
2884       { "Tag Length", "erf.meta.tag.len",
2885         FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
2886     { &hf_erf_meta_tag_unknown,
2887       { "Value", "erf.meta.unknown",
2888         FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }
2889   };
2890
2891   static gint *ett[] = {
2892     &ett_erf,
2893     &ett_erf_pseudo_hdr,
2894     &ett_erf_rectype,
2895     &ett_erf_flags,
2896     &ett_erf_mc_hdlc,
2897     &ett_erf_mc_raw,
2898     &ett_erf_mc_atm,
2899     &ett_erf_mc_rawlink,
2900     &ett_erf_mc_aal5,
2901     &ett_erf_mc_aal2,
2902     &ett_erf_aal2,
2903     &ett_erf_eth,
2904     &ett_erf_meta,
2905     &ett_erf_meta_tag,
2906     &ett_erf_source
2907   };
2908
2909   static const enum_val_t erf_hdlc_options[] = {
2910     { "chdlc",  "Cisco HDLC",       ERF_HDLC_CHDLC },
2911     { "ppp",    "PPP serial",       ERF_HDLC_PPP },
2912     { "frelay", "Frame Relay",      ERF_HDLC_FRELAY },
2913     { "mtp2",   "SS7 MTP2",         ERF_HDLC_MTP2 },
2914     { "guess",  "Attempt to guess", ERF_HDLC_GUESS },
2915     { NULL, NULL, 0 }
2916   };
2917
2918   static const enum_val_t erf_aal5_options[] = {
2919     { "guess", "Attempt to guess", ERF_AAL5_GUESS },
2920     { "llc",   "LLC multiplexed",  ERF_AAL5_LLC },
2921     { "unspec", "Unspecified", ERF_AAL5_UNSPEC },
2922     { NULL, NULL, 0 }
2923   };
2924
2925   static ei_register_info ei[] = {
2926       { &ei_erf_checksum_error, { "erf.checksum.error", PI_CHECKSUM, PI_ERROR, "ERF MC FCS Error", EXPFILL }},
2927       { &ei_erf_packet_loss, { "erf.packet_loss", PI_SEQUENCE, PI_WARN, "Packet loss occurred between previous and current packet", EXPFILL }},
2928       { &ei_erf_extension_headers_not_shown, { "erf.ehdr.more_not_shown", PI_SEQUENCE, PI_WARN, "More extension headers were present, not shown", EXPFILL }},
2929       { &ei_erf_meta_section_len_error, { "erf.meta.section_len.error", PI_PROTOCOL, PI_ERROR, "MetaERF Section Length incorrect", EXPFILL }},
2930       { &ei_erf_meta_reset, { "erf.meta.metadata_reset", PI_PROTOCOL, PI_WARN, "MetaERF metadata reset", EXPFILL }}
2931   };
2932
2933   module_t *erf_module;
2934   expert_module_t* expert_erf;
2935
2936   proto_erf = proto_register_protocol("Extensible Record Format", "ERF", "erf");
2937   erf_handle = register_dissector("erf", dissect_erf, proto_erf);
2938
2939   init_meta_tags();
2940
2941   proto_register_field_array(proto_erf, hf, array_length(hf));
2942   proto_register_subtree_array(ett, array_length(ett));
2943   expert_erf = expert_register_protocol(proto_erf);
2944   expert_register_field_array(expert_erf, ei, array_length(ei));
2945
2946   /* Register per-section MetaERF fields */
2947   proto_register_field_array(proto_erf, (hf_register_info*) wmem_array_get_raw(erf_meta_index.hfri), (int) wmem_array_get_count(erf_meta_index.hfri));
2948   proto_register_subtree_array((gint**) wmem_array_get_raw(erf_meta_index.ett), (int) wmem_array_get_count(erf_meta_index.ett));
2949
2950   erf_module = prefs_register_protocol(proto_erf, NULL);
2951
2952   prefs_register_enum_preference(erf_module, "hdlc_type", "ERF_HDLC Layer 2",
2953                                  "Protocol encapsulated in HDLC records",
2954                                  &erf_hdlc_type, erf_hdlc_options, FALSE);
2955
2956   prefs_register_bool_preference(erf_module, "rawcell_first",
2957                                  "Raw ATM cells are first cell of AAL5 PDU",
2958                                  "Whether raw ATM cells should be treated as "
2959                                  "the first cell of an AAL5 PDU",
2960                                  &erf_rawcell_first);
2961
2962   prefs_register_enum_preference(erf_module, "aal5_type",
2963                                  "ATM AAL5 packet type",
2964                                  "Protocol encapsulated in ATM AAL5 packets",
2965                                  &erf_aal5_type, erf_aal5_options, FALSE);
2966
2967   prefs_register_bool_preference(erf_module, "ethfcs",
2968                                  "Ethernet packets have FCS",
2969                                  "Whether the FCS is present in Ethernet packets",
2970                                  &erf_ethfcs);
2971
2972   erf_dissector_table = register_dissector_table("erf.types.type", "Type", proto_erf, FT_UINT8, BASE_DEC, DISSECTOR_TABLE_NOT_ALLOW_DUPLICATE);
2973
2974   register_init_routine(erf_init_dissection);
2975   /* No extra cleanup needed */
2976 }
2977
2978 void
2979 proto_reg_handoff_erf(void)
2980 {
2981   dissector_add_uint("wtap_encap", WTAP_ENCAP_ERF, erf_handle);
2982   /* Also register dissector for MetaERF non-packet records */
2983   dissector_add_uint("wtap_fts_rec", WTAP_FILE_TYPE_SUBTYPE_ERF, erf_handle);
2984
2985   /* Get handles for serial line protocols */
2986   chdlc_handle  = find_dissector_add_dependency("chdlc", proto_erf);
2987   ppp_handle    = find_dissector_add_dependency("ppp_hdlc", proto_erf);
2988   frelay_handle = find_dissector_add_dependency("fr", proto_erf);
2989   mtp2_handle   = find_dissector_add_dependency("mtp2_with_crc", proto_erf);
2990
2991   /* Get handle for ATM dissector */
2992   atm_untruncated_handle = find_dissector_add_dependency("atm_untruncated", proto_erf);
2993
2994   sdh_handle = find_dissector_add_dependency("sdh", proto_erf);
2995 }
2996
2997 /*
2998  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
2999  *
3000  * Local Variables:
3001  * c-basic-offset: 2
3002  * tab-width: 8
3003  * indent-tabs-mode: nil
3004  * End:
3005  *
3006  * ex: set shiftwidth=2 tabstop=8 expandtab:
3007  * :indentSize=2:tabSize=8:noTabs=true:
3008  */