27517ec58f0d977e12abb21297d3cc2e9f2a475d
[obnox/wireshark/wip.git] / epan / dissectors / packet-meta.c
1 /* Routines for 'Metadata' disassembly
2  *
3  * $Id$
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include <string.h>
29
30 #include <glib.h>
31 #include <epan/packet.h>
32 #include <epan/expert.h>
33
34 #include "packet-meta.h"
35 #include "packet-sscop.h"
36 #include "wiretap/erf.h"
37
38 static int proto_meta = -1;
39 extern int proto_sscop;
40 extern int proto_malformed;
41
42 /* fields */
43 static int hf_meta_schema = -1;
44 static int hf_meta_hdrlen = -1;
45 static int hf_meta_proto = -1;
46 static int hf_meta_reserved = -1;
47 static int hf_meta_item = -1;
48 static int hf_meta_item_id = -1;
49 static int hf_meta_item_type = -1;
50 static int hf_meta_item_len = -1;
51 static int hf_meta_item_data = -1;
52 /* specific fields */
53 static int hf_meta_item_direction = -1;
54 static int hf_meta_item_ts = -1;
55 static int hf_meta_item_phylinkid = -1;
56 static int hf_meta_item_nsapi = -1;
57 static int hf_meta_item_imsi = -1;
58 static int hf_meta_item_imei = -1;
59 static int hf_meta_item_signaling = -1;
60 static int hf_meta_item_incomplete = -1;
61 static int hf_meta_item_deciphered = -1;
62 static int hf_meta_item_apn = -1;
63 static int hf_meta_item_rat = -1;
64 static int hf_meta_item_aal5proto = -1;
65 static int hf_meta_item_cell = -1;
66 static int hf_meta_item_localdevid = -1;
67 static int hf_meta_item_remotedevid = -1;
68 static int hf_meta_item_tapgroupid = -1;
69 static int hf_meta_item_tlli = -1;
70 static int hf_meta_item_calling = -1;
71 static int hf_meta_item_called = -1;
72
73 /* subtrees */
74 static gint ett_meta = -1;
75 static gint ett_meta_item = -1;
76
77 /* default handle */
78 static dissector_handle_t data_handle;
79 static dissector_handle_t atm_untrunc_handle;
80 static dissector_handle_t sscf_nni_handle;
81 static dissector_handle_t alcap_handle;
82 static dissector_handle_t nbap_handle;
83 static dissector_handle_t ethwithfcs_handle;
84 static dissector_handle_t ethwithoutfcs_handle;
85 static dissector_handle_t fphint_handle;
86 static dissector_handle_t erf_handle;
87
88 static const value_string meta_schema_vals[] = {
89     { META_SCHEMA_PCAP,     "PCAP" },
90     { META_SCHEMA_DXT,      "DXT" },
91     { 0, NULL }
92 };
93
94 static const value_string meta_proto_vals[] = {
95     { META_PROTO_DXT_ETHERNET,      "Ethernet without FCS" },
96     { META_PROTO_DXT_ETHERNET_CRC,  "Ethernet with FCS" },
97     { META_PROTO_DXT_FP_HINT,       "FP Hint" },
98     { META_PROTO_DXT_ERF_AAL5,      "ERF AAL5" },
99     { META_PROTO_DXT_ATM_AAL2,      "ATM AAL2" },
100     { META_PROTO_DXT_ATM,           "ATM" },
101     { 0, NULL }
102 };
103
104 static const value_string meta_type_vals[] = {
105     { META_TYPE_NONE,       "NONE" },
106     { META_TYPE_BOOLEAN,    "BOOLEAN" },
107     { META_TYPE_UINT8,      "UINT8" },
108     { META_TYPE_UINT16,     "UINT16" },
109     { META_TYPE_UINT32,     "UINT32" },
110     { META_TYPE_UINT64,     "UINT64" },
111     { META_TYPE_STRING,     "STRING" },
112     { 0, NULL }
113 };
114
115 /* TODO: this must be on a per-schema basis! */
116 static const value_string meta_id_vals[] = {
117     { META_ID_NULL,         "NULL" },
118     { META_ID_DIRECTION,    "Direction" },
119     { META_ID_SIGNALING,    "Signaling" },
120     { META_ID_INCOMPLETE,   "Incomplete" },
121     { META_ID_DECIPHERED,   "Deciphered" },
122     { META_ID_PAYLOADCUT,   "Payload cutted" },
123     { META_ID_TIMESTAMP64,  "Timestamp" },
124     { META_ID_AAL5PROTO,    "AAL5 Protocol Type" },
125     { META_ID_PHYLINKID,    "Physical Link ID" },
126     { META_ID_LOCALDEVID,   "Local Device ID" },
127     { META_ID_REMOTEDEVID,  "Remote Device ID" },
128     { META_ID_TAPGROUPID,   "Tap Group ID" },
129     { META_ID_IMSI,         "IMSI" },
130     { META_ID_IMEI,         "IMEI" },
131     { META_ID_CELL,         "Cell" },
132     { META_ID_TLLI,         "TLLI" },
133     { META_ID_NSAPI,        "NSAPI" },
134     { META_ID_APN,          "APN" },
135     { META_ID_RAT,          "RAT" },
136     { META_ID_CALLING,      "Calling Station ID" },
137     { META_ID_CALLED,       "Called Station ID" },
138     { 0, NULL }
139 };
140
141 #define META_AAL5PROTO_MTP3     2
142 #define META_AAL5PROTO_NS       3
143 #define META_AAL5PROTO_ALCAP    5
144 #define META_AAL5PROTO_NBAP     6
145 static const value_string meta_aal5proto_vals[] = {
146     { META_AAL5PROTO_MTP3,  "SSCOP MTP3" },
147     { META_AAL5PROTO_ALCAP, "SSCOP ALCAP" },
148     { META_AAL5PROTO_NBAP,  "SSCOP NBAP" },
149     { META_AAL5PROTO_NS,    "GPRS NS" },
150     { 0, NULL }
151 };
152
153 static const value_string meta_direction_vals[] = {
154     { 0,    "Up" },
155     { 1,    "Down" },
156     { 0,    NULL }
157 };
158
159 static guint16 skip_item(proto_tree *meta_tree, tvbuff_t *tvb, packet_info *pinfo _U_, guint16 offs)
160 {
161     guint16 id;
162     guint8 type, len, aligned_len, total_len;
163     proto_tree *item_tree;
164     proto_item *subti;
165
166     id = tvb_get_letohs(tvb, offs); offs += 2;
167     type = tvb_get_guint8(tvb, offs); offs++;
168     len = tvb_get_guint8(tvb, offs); offs++;
169     aligned_len = (len + 3) & 0xfffc;
170     total_len = aligned_len + 4; /* 4: id, type, len fields */
171
172     subti = proto_tree_add_item(meta_tree, hf_meta_item, tvb, offs - 4,
173         aligned_len + 4, ENC_NA);
174     item_tree = proto_item_add_subtree(subti, ett_meta_item);
175     proto_tree_add_uint(item_tree, hf_meta_item_id, tvb, offs - 4, 2, id);
176     proto_tree_add_uint(item_tree, hf_meta_item_type, tvb, offs - 2, 1, type);
177     proto_tree_add_uint(item_tree, hf_meta_item_len,
178         tvb, offs - 1, 1, len);
179     if (len > 0)
180         proto_tree_add_item(item_tree, hf_meta_item_data,
181             tvb, offs, len, ENC_NA);
182
183     return total_len;
184 }
185
186 /*
187 * offs: current offset in tvb
188 */
189 static guint16 evaluate_meta_item_pcap(proto_tree *meta_tree, tvbuff_t *tvb, packet_info *pinfo, guint16 offs)
190 {
191     guint16 id;
192     guint8 type, len, aligned_len, total_len;
193     proto_tree *item_tree;
194     proto_item *subti;
195     /* field values */
196     guint8 dir;
197     guint64 ts;
198
199     id = tvb_get_letohs(tvb, offs); offs += 2;
200     type = tvb_get_guint8(tvb, offs); offs++;
201     len = tvb_get_guint8(tvb, offs); offs++;
202     aligned_len = (len + 3) & 0xfffc;
203     total_len = aligned_len + 4; /* 4: id, type, len fields */
204
205     switch (id) {
206         case META_ID_DIRECTION:
207             dir = tvb_get_guint8(tvb, offs);
208             pinfo->p2p_dir = dir == META_DIR_UP ? P2P_DIR_RECV : P2P_DIR_SENT;
209             proto_tree_add_uint(meta_tree, hf_meta_item_direction, tvb, offs, 1, dir);
210             break;
211         case META_ID_TIMESTAMP64:
212             ts = tvb_get_letoh64(tvb, offs);
213             proto_tree_add_uint64(meta_tree, hf_meta_item_ts, tvb, offs, 8, ts);
214             break;
215         case META_ID_SIGNALING:
216             proto_tree_add_boolean(meta_tree, hf_meta_item_signaling, tvb,
217                 offs, 0, 1);
218             break;
219         case META_ID_INCOMPLETE:
220             proto_tree_add_boolean(meta_tree, hf_meta_item_incomplete, tvb,
221                 offs, 0, 1);
222             break;
223         default:
224             subti = proto_tree_add_item(meta_tree, hf_meta_item, tvb, offs - 4,
225                 aligned_len + 4, ENC_NA);
226             item_tree = proto_item_add_subtree(subti, ett_meta_item);
227             proto_tree_add_uint(item_tree, hf_meta_item_id, tvb, offs - 4, 2, id);
228             proto_tree_add_uint(item_tree, hf_meta_item_type, tvb, offs - 2, 1, type);
229             proto_tree_add_uint(item_tree, hf_meta_item_len,
230                 tvb, offs - 1, 1, len);
231             if (len > 0)
232                 proto_tree_add_item(item_tree, hf_meta_item_data,
233                     tvb, offs, len, ENC_NA);
234     }
235     return total_len;
236 }
237
238 /*
239 * offs: current offset in tvb
240 */
241 static guint16 evaluate_meta_item_dxt(proto_tree *meta_tree, tvbuff_t *tvb, packet_info *pinfo, guint16 offs)
242 {
243     guint16 id;
244     guint8 type, len, aligned_len, total_len;
245     proto_tree *item_tree;
246     proto_item *subti;
247     /* field values */
248     guint8 dir, nsapi, rat, aal5proto, *apn, *calling, *called;
249     guint16 phylinkid, localdevid, remotedevid, tapgroupid;
250     guint32 tlli;
251     guint64 ts, imsi, imei, cell;
252     sscop_payload_info *p_sscop_info;
253
254     id = tvb_get_letohs(tvb, offs); offs += 2;
255     type = tvb_get_guint8(tvb, offs); offs++;
256     len = tvb_get_guint8(tvb, offs); offs++;
257     aligned_len = (len + 3) & 0xfffc;
258     total_len = aligned_len + 4; /* 4: id, type, len fields */
259
260     switch (id) {
261         case META_ID_DIRECTION:
262             dir = tvb_get_guint8(tvb, offs);
263             pinfo->p2p_dir = dir == META_DIR_UP ? P2P_DIR_RECV : P2P_DIR_SENT;
264             proto_tree_add_uint(meta_tree, hf_meta_item_direction, tvb, offs, 1, dir);
265             break;
266         case META_ID_TIMESTAMP64:
267             ts = tvb_get_letoh64(tvb, offs);
268             proto_tree_add_uint64(meta_tree, hf_meta_item_ts, tvb, offs, 8, ts);
269             break;
270         case META_ID_PHYLINKID:
271             phylinkid = tvb_get_letohs(tvb, offs);
272             pinfo->link_number = phylinkid;
273             proto_tree_add_uint(meta_tree, hf_meta_item_phylinkid, tvb,
274                 offs, 2, phylinkid);
275             break;
276         case META_ID_NSAPI:
277             nsapi = tvb_get_guint8(tvb, offs);
278             proto_tree_add_uint(meta_tree, hf_meta_item_nsapi, tvb,
279                 offs, 1, nsapi);
280             break;
281         case META_ID_IMSI:
282             imsi = tvb_get_letoh64(tvb, offs);
283             proto_tree_add_uint64(meta_tree, hf_meta_item_imsi, tvb,
284                 offs, 8, imsi);
285             break;
286         case META_ID_IMEI:
287             imei = tvb_get_letoh64(tvb, offs);
288             proto_tree_add_uint64(meta_tree, hf_meta_item_imei, tvb,
289                 offs, 8, imei);
290             break;
291         case META_ID_APN:
292             apn = tvb_get_string(tvb, offs, len);
293             proto_tree_add_string(meta_tree, hf_meta_item_apn, tvb,
294                 offs, len, apn);
295             break;
296         case META_ID_RAT:
297             rat = tvb_get_guint8(tvb, offs);
298             proto_tree_add_uint(meta_tree, hf_meta_item_rat, tvb,
299                 offs, 1, rat);
300             break;
301         case META_ID_CELL:
302             cell = tvb_get_ntoh64(tvb, offs);
303             proto_tree_add_uint64(meta_tree, hf_meta_item_cell, tvb,
304                 offs, 8, cell);
305             break;
306         case META_ID_SIGNALING:
307             proto_tree_add_boolean(meta_tree, hf_meta_item_signaling, tvb,
308                 offs, 0, 1);
309             break;
310         case META_ID_INCOMPLETE:
311             proto_tree_add_boolean(meta_tree, hf_meta_item_incomplete, tvb,
312                 offs, 0, 1);
313             break;
314         case META_ID_DECIPHERED:
315             proto_tree_add_boolean(meta_tree, hf_meta_item_deciphered, tvb,
316                 offs, 0, 1);
317             break;
318         case META_ID_AAL5PROTO:
319             aal5proto = tvb_get_guint8(tvb, offs);
320             p_sscop_info = p_get_proto_data(pinfo->fd, proto_sscop);
321             if (!p_sscop_info) {
322                 p_sscop_info = se_alloc0(sizeof(sscop_payload_info));
323                 p_add_proto_data(pinfo->fd, proto_sscop, p_sscop_info);
324             }
325             switch (aal5proto) {
326                 case META_AAL5PROTO_MTP3:
327                     p_sscop_info->subdissector = sscf_nni_handle;
328                     break;
329                 case META_AAL5PROTO_ALCAP:
330                     p_sscop_info->subdissector = alcap_handle;
331                     break;
332                 case META_AAL5PROTO_NBAP:
333                     p_sscop_info->subdissector = nbap_handle;
334                     break;
335                 case META_AAL5PROTO_NS:
336                     /* hint for ATM dissector that this frame contains GPRS NS */
337                     memset(&pinfo->pseudo_header->atm, 0, sizeof(pinfo->pseudo_header->atm));
338                     pinfo->pseudo_header->atm.type = TRAF_GPRS_NS;
339                     break;
340                 /* TODO: check for additional protos on Iu 802 LLC/SNAP ... */
341                 default:
342                     /* TODO: add warning */
343                     p_remove_proto_data(pinfo->fd, proto_sscop);
344             }
345             proto_tree_add_uint(meta_tree, hf_meta_item_aal5proto, tvb,
346                 offs, 1, aal5proto);
347             break;
348         case META_ID_LOCALDEVID:
349             localdevid = tvb_get_letohs(tvb, offs);
350             proto_tree_add_uint(meta_tree, hf_meta_item_localdevid, tvb,
351                 offs, 2, localdevid);
352             break;
353         case META_ID_REMOTEDEVID:
354             remotedevid = tvb_get_letohs(tvb, offs);
355             proto_tree_add_uint(meta_tree, hf_meta_item_remotedevid, tvb,
356                 offs, 2, remotedevid);
357             break;
358         case META_ID_TAPGROUPID:
359             tapgroupid = tvb_get_letohs(tvb, offs);
360             proto_tree_add_uint(meta_tree, hf_meta_item_tapgroupid, tvb,
361                 offs, 2, tapgroupid);
362             break;
363         case META_ID_TLLI:
364             tlli = tvb_get_letohs(tvb, offs);
365             proto_tree_add_uint(meta_tree, hf_meta_item_tlli, tvb,
366                 offs, 4, tlli);
367             break;
368         case META_ID_CALLING:
369             calling = tvb_get_string(tvb, offs, len);
370             proto_tree_add_string(meta_tree, hf_meta_item_calling, tvb,
371                 offs, len, calling);
372             break;
373         case META_ID_CALLED:
374             called = tvb_get_string(tvb, offs, len);
375             proto_tree_add_string(meta_tree, hf_meta_item_called, tvb,
376                 offs, len, called);
377             break;
378         default:
379             subti = proto_tree_add_item(meta_tree, hf_meta_item, tvb, offs - 4,
380                 aligned_len + 4, ENC_NA);
381             item_tree = proto_item_add_subtree(subti, ett_meta_item);
382             proto_tree_add_uint(item_tree, hf_meta_item_id, tvb, offs - 4, 2, id);
383             proto_tree_add_uint(item_tree, hf_meta_item_type, tvb, offs - 2, 1, type);
384             proto_tree_add_uint(item_tree, hf_meta_item_len,
385                 tvb, offs - 1, 1, len);
386             if (len > 0)
387                 proto_tree_add_item(item_tree, hf_meta_item_data,
388                     tvb, offs, len, ENC_NA);
389     }
390     return total_len;
391 }
392
393 /*
394  * offs: current offset within tvb
395  * header_length: length of meta header
396  */
397 static gint32 evaluate_meta_items(guint16 schema, tvbuff_t *tvb, packet_info *pinfo,
398     proto_tree *meta_tree, guint16 offs, gint32 header_length)
399 {
400     gint16 item_len;
401     gint32 total_len = 0;
402     while (total_len < header_length) {
403         switch (schema) {
404             case META_SCHEMA_DXT:
405                 item_len = evaluate_meta_item_dxt(meta_tree, tvb, pinfo, offs + total_len);
406                 break;
407             case META_SCHEMA_PCAP:
408                 item_len = evaluate_meta_item_pcap(meta_tree, tvb, pinfo, offs + total_len);
409                 break;
410             default:
411                 item_len = skip_item(meta_tree, tvb, pinfo, offs + total_len);
412         }
413         if (item_len < 4) { /* 4 is the minimum length of an item: id + type + length field */
414             proto_item *malformed;
415             malformed = proto_tree_add_protocol_format(meta_tree,
416                 proto_malformed, tvb, offs, -1, "[Malformed Packet: %s]", pinfo->current_proto);
417             expert_add_info_format(pinfo, malformed, PI_MALFORMED, PI_ERROR,
418                 "Malformed Packet (wrong item encoding)");
419             return -1;
420         }
421         total_len += item_len;
422     }
423     return total_len;
424 }
425
426 static void
427 dissect_meta(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
428 {
429 #define META_HEADER_SIZE 8
430     guint16 schema, proto, hdrlen, reserved;
431     gint32 item_len;
432     guint32 aal2_ext, atm_hdr;
433     proto_tree *meta_tree = NULL;
434     proto_item *ti = NULL;
435     tvbuff_t *next_tvb;
436     dissector_handle_t next_dissector = data_handle;
437
438     if (check_col(pinfo->cinfo, COL_PROTOCOL))
439         col_set_str(pinfo->cinfo, COL_PROTOCOL, "META");
440
441     schema = tvb_get_letohs(tvb, 0);
442     hdrlen = tvb_get_letohs(tvb, 2);
443     proto = tvb_get_letohs(tvb, 4);
444     reserved = tvb_get_letohs(tvb, 6);
445
446     if (tree) {
447         ti = proto_tree_add_item(tree, proto_meta, tvb, 0, hdrlen + 4, ENC_NA);
448         meta_tree = proto_item_add_subtree(ti, ett_meta);
449         proto_tree_add_uint(meta_tree, hf_meta_schema, tvb, 0, 2, schema);
450         proto_tree_add_uint(meta_tree, hf_meta_hdrlen, tvb, 2, 2, hdrlen);
451         proto_tree_add_uint(meta_tree, hf_meta_proto, tvb, 4, 2, proto);
452         proto_tree_add_uint(meta_tree, hf_meta_reserved, tvb, 6, 2, reserved);
453     }
454     item_len = evaluate_meta_items(schema, tvb, pinfo, meta_tree, META_HEADER_SIZE, hdrlen);
455
456     if (item_len < 0) {
457         /* evaluate_meta_items signalled an error */
458         return; /* stop parsing */
459     }
460
461     if (hdrlen != item_len) {
462         expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR, "Invalid Header Length");
463         proto_tree_add_text(tree, tvb, hdrlen+4, -1, "[Malformed Packet]");
464         return;
465     }
466
467     /* find next subdissector based on the chosen schema */
468     switch (schema) {
469         case META_SCHEMA_PCAP:
470             /* TODO */
471             break;
472         case META_SCHEMA_DXT:
473             switch (proto) {
474                 case META_PROTO_DXT_ETHERNET:
475                     next_dissector = ethwithoutfcs_handle;
476                     break;
477                 case META_PROTO_DXT_ETHERNET_CRC:
478                     next_dissector = ethwithfcs_handle;
479                     break;
480                 case META_PROTO_DXT_FP_HINT:
481                     next_dissector = fphint_handle;
482                     break;
483                 case META_PROTO_DXT_ATM:
484                     next_dissector = atm_untrunc_handle;
485                     pinfo->pseudo_header->atm.aal = AAL_OAMCELL;
486                     pinfo->pseudo_header->atm.type = TRAF_UNKNOWN;
487                     break;
488                 case META_PROTO_DXT_ATM_AAL2:
489                     aal2_ext = tvb_get_ntohl(tvb, item_len + META_HEADER_SIZE); item_len += 4;
490                     atm_hdr = tvb_get_ntohl(tvb, item_len + META_HEADER_SIZE); item_len += 4;
491                     memset(&pinfo->pseudo_header->atm, 0, sizeof(pinfo->pseudo_header->atm));
492                     pinfo->pseudo_header->atm.aal = AAL_2;
493                     /* pinfo->pseudo_header->atm.flags = pinfo->p2p_dir; */
494                     pinfo->pseudo_header->atm.vpi = ((atm_hdr & 0x0ff00000) >> 20);
495                     pinfo->pseudo_header->atm.vci = ((atm_hdr & 0x000ffff0) >>  4);
496                     pinfo->pseudo_header->atm.aal2_cid = aal2_ext & 0x000000ff;
497                     pinfo->pseudo_header->atm.type = TRAF_UMTS_FP;
498                     next_dissector = atm_untrunc_handle;
499                     break;
500                 case META_PROTO_DXT_ERF_AAL5:
501                     atm_hdr = tvb_get_ntohl(tvb, item_len + META_HEADER_SIZE); item_len += 4;
502                     pinfo->pseudo_header->atm.vpi = ((atm_hdr & 0x0ff00000) >> 20);
503                     pinfo->pseudo_header->atm.vci = ((atm_hdr & 0x000ffff0) >>  4);
504                     pinfo->pseudo_header->atm.aal = AAL_5;
505                     next_dissector = atm_untrunc_handle;
506                     break;
507             }
508     }
509     next_tvb = tvb_new_subset(tvb, item_len + META_HEADER_SIZE, -1, -1);
510     call_dissector(next_dissector, next_tvb, pinfo, tree);
511 }
512
513 void
514 proto_register_meta(void)
515 {
516     static hf_register_info hf[] = {
517         /* metadata header */
518         { &hf_meta_schema, { "Schema", "meta.schema", FT_UINT16, BASE_DEC, VALS(meta_schema_vals), 0, NULL, HFILL } },
519         { &hf_meta_hdrlen, { "Header Length", "meta.hdrlen", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
520         { &hf_meta_proto, { "Protocol", "meta.proto", FT_UINT16, BASE_DEC, VALS(meta_proto_vals), 0, NULL, HFILL } },
521         { &hf_meta_reserved, { "Reserved", "meta.reserved", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } },
522
523         /* general meta item */
524         { &hf_meta_item, { "Unknown Item", "meta.item", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } },
525         { &hf_meta_item_id, { "Item ID", "meta.item.id", FT_UINT16, BASE_HEX, VALS(meta_id_vals), 0x0, NULL, HFILL } },
526         { &hf_meta_item_type, { "Item Type", "meta.item.type", FT_UINT8, BASE_HEX, VALS(meta_type_vals), 0x0, NULL, HFILL } },
527         { &hf_meta_item_len, { "Item Length", "meta.item.len", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } },
528         { &hf_meta_item_data, { "Item Data", "meta.item.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
529
530         /* specific meta items */
531         { &hf_meta_item_direction, { "Direction", "meta.direction", FT_UINT8, BASE_DEC, VALS(meta_direction_vals), 0, NULL, HFILL } },
532         { &hf_meta_item_ts, { "Timestamp", "meta.timestamp", FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL } },
533         { &hf_meta_item_phylinkid, { "Physical Link ID", "meta.phylinkid", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
534         { &hf_meta_item_nsapi, { "NSAPI", "meta.nsapi", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } },
535         { &hf_meta_item_imsi, { "IMSI", "meta.imsi", FT_UINT64, BASE_HEX, NULL, 0, NULL, HFILL } },
536         { &hf_meta_item_imei, { "IMEI", "meta.imei", FT_UINT64, BASE_HEX, NULL, 0, NULL, HFILL } },
537         { &hf_meta_item_signaling, { "Signaling", "meta.signaling", FT_BOOLEAN, BASE_NONE, NULL, 0, NULL, HFILL } },
538         { &hf_meta_item_incomplete, { "Incomplete", "meta.incomplete", FT_BOOLEAN, BASE_NONE, NULL, 0, NULL, HFILL } },
539         { &hf_meta_item_deciphered, { "Deciphered", "meta.deciphered", FT_BOOLEAN, BASE_NONE, NULL, 0, NULL, HFILL } },
540         { &hf_meta_item_apn, { "APN", "meta.apn", FT_STRINGZ, BASE_NONE, NULL, 0, NULL, HFILL } },
541         { &hf_meta_item_rat, { "RAT", "meta.rat", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } },
542         { &hf_meta_item_aal5proto, { "AAL5 Protocol Type", "meta.aal5proto", FT_UINT8, BASE_DEC, VALS(meta_aal5proto_vals), 0, NULL, HFILL } },
543         { &hf_meta_item_cell, { "Cell", "meta.cell", FT_UINT64, BASE_HEX, NULL, 0, NULL, HFILL } },
544
545         { &hf_meta_item_localdevid, { "Local Device ID", "meta.localdevid", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
546         { &hf_meta_item_remotedevid, { "Remote Device ID", "meta.remotedevid", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
547         { &hf_meta_item_tapgroupid, { "Tap Group ID", "meta.tapgroupid", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
548         { &hf_meta_item_tlli, { "TLLI", "meta.tlli", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
549         { &hf_meta_item_calling, { "Calling Station ID", "meta.calling", FT_STRINGZ, BASE_NONE, NULL, 0, NULL, HFILL } },
550         { &hf_meta_item_called, { "Called Station ID", "meta.called", FT_STRINGZ, BASE_NONE, NULL, 0, NULL, HFILL } },
551     };
552
553     static gint *ett[] = {
554         &ett_meta,
555         &ett_meta_item
556     };
557
558     proto_meta = proto_register_protocol("Metadata", "META", "meta");
559     register_dissector("meta", dissect_meta, proto_meta);
560
561     proto_register_field_array(proto_meta, hf, array_length(hf));
562     proto_register_subtree_array(ett, array_length(ett));
563 }
564
565 void
566 proto_reg_handoff_meta(void)
567 {
568 #if 0   /* enable once WTAP_ENCAP_META exists */
569     dissector_handle_t meta_handle;
570
571     meta_handle = find_dissector("meta");
572     dissector_add_uint("wtap_encap", WTAP_ENCAP_META, meta_handle);
573 #endif
574     data_handle = find_dissector("data");
575     alcap_handle = find_dissector("alcap");
576     atm_untrunc_handle = find_dissector("atm_untruncated");
577     nbap_handle = find_dissector("nbap");
578     sscf_nni_handle = find_dissector("sscf-nni");
579     ethwithfcs_handle = find_dissector("eth_withfcs");
580     ethwithoutfcs_handle = find_dissector("eth_withoutfcs");
581     fphint_handle = find_dissector("fp_hint");
582     erf_handle = find_dissector("erf");
583 }