1 /* Routines for 'Metadata' disassembly
2  *
3  * Wireshark - Network traffic analyzer
4  * By Gerald Combs <gerald@wireshark.org>
5  * Copyright 1998 Gerald Combs
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  */
9 
10 #include "config.h"
11 
12 
13 #include <epan/packet.h>
14 #include <wiretap/wtap.h>
15 #include <epan/expert.h>
16 #include <epan/proto_data.h>
17 #include "packet-sscop.h"
18 #include "packet-gsm_a_common.h"
19 
20 void proto_register_meta(void);
21 void proto_reg_handoff_meta(void);
22 
23 /* schemas */
24 #define META_SCHEMA_PCAP        1
25 #define META_SCHEMA_DXT         2
26 
27 /* protocols */
28 #define META_PROTO_DXT_ETHERNET        1
29 #define META_PROTO_DXT_ETHERNET_CRC   36
30 #define META_PROTO_DXT_ATM            41
31 #define META_PROTO_DXT_ERF_AAL5       49
32 #define META_PROTO_DXT_M3UA           61
33 #define META_PROTO_DXT_NBAP           69
34 #define META_PROTO_DXT_ATM_AAL2       76
35 #define META_PROTO_DXT_FP_HINT        82
36 #define META_PROTO_DXT_HDLC          106
37 #define META_PROTO_DXT_CONTAINER     127
38 #define META_PROTO_DXT_FP_CAPTURE    193
39 #define META_PROTO_DXT_UTRAN_CAPSULE 194
40 
41 /* data types */
42 #define META_TYPE_NONE             0
43 #define META_TYPE_BOOLEAN          1
44 #define META_TYPE_UINT8            2
45 #define META_TYPE_UINT16           3
46 #define META_TYPE_UINT32           4
47 #define META_TYPE_UINT64           5
48 #define META_TYPE_STRING          16
49 
50 /* item ids */
51 #define META_ID_NULL               0
52 #define META_ID_DIRECTION          1
53 #define META_ID_SIGNALING          2
54 #define META_ID_INCOMPLETE         3
55 #define META_ID_DECIPHERED         4
56 #define META_ID_PAYLOADCUT         5
57 #define META_ID_TIMESTAMP64        6
58 #define META_ID_AAL5PROTO          7
59 #define META_ID_PHYLINKID        256
60 #define META_ID_LOCALDEVID       257
61 #define META_ID_REMOTEDEVID      258
62 #define META_ID_TAPGROUPID       259
63 #define META_ID_IMSI            1024
64 #define META_ID_IMEI            1025
65 #define META_ID_CELL            1026
66 #define META_ID_TLLI            1027
67 #define META_ID_NSAPI           1028
68 #define META_ID_APN             1029
69 #define META_ID_RAT             1030
70 #define META_ID_CALLING         1031
71 #define META_ID_CALLED          1032
72 
73 enum meta_direction {
74     META_DIR_UP,
75     META_DIR_DOWN
76 };
77 
78 static int proto_meta = -1;
79 extern int proto_sscop;
80 
81 /* fields */
82 static int hf_meta_schema = -1;
83 static int hf_meta_hdrlen = -1;
84 static int hf_meta_proto = -1;
85 static int hf_meta_reserved = -1;
86 static int hf_meta_item = -1;
87 static int hf_meta_item_id = -1;
88 static int hf_meta_item_type = -1;
89 static int hf_meta_item_len = -1;
90 static int hf_meta_item_data = -1;
91 /* specific fields */
92 static int hf_meta_item_direction = -1;
93 static int hf_meta_item_ts = -1;
94 static int hf_meta_item_phylinkid = -1;
95 static int hf_meta_item_nsapi = -1;
96 static int hf_meta_item_imsi_value = -1;
97 static int hf_meta_item_imsi_digits = -1;
98 static int hf_meta_item_imei_value = -1;
99 static int hf_meta_item_imei_digits = -1;
100 static int hf_meta_item_signaling = -1;
101 static int hf_meta_item_incomplete = -1;
102 static int hf_meta_item_deciphered = -1;
103 static int hf_meta_item_apn = -1;
104 static int hf_meta_item_rat = -1;
105 static int hf_meta_item_aal5proto = -1;
106 static int hf_meta_item_cell = -1;
107 static int hf_meta_item_localdevid = -1;
108 static int hf_meta_item_remotedevid = -1;
109 static int hf_meta_item_tapgroupid = -1;
110 static int hf_meta_item_tlli = -1;
111 static int hf_meta_item_calling = -1;
112 static int hf_meta_item_called = -1;
113 
114 /* subtrees */
115 static gint ett_meta = -1;
116 static gint ett_meta_item = -1;
117 static gint ett_meta_cell = -1;
118 static gint ett_meta_imsi = -1;
119 static gint ett_meta_imei = -1;
120 
121 static expert_field ei_meta_malformed = EI_INIT;
122 static expert_field ei_meta_invalid_header = EI_INIT;
123 
124 /* default handle */
125 static dissector_handle_t data_handle;
126 static dissector_handle_t atm_untrunc_handle;
127 static dissector_handle_t sscf_nni_handle;
128 static dissector_handle_t alcap_handle;
129 static dissector_handle_t nbap_handle;
130 static dissector_handle_t ethwithfcs_handle;
131 static dissector_handle_t ethwithoutfcs_handle;
132 static dissector_handle_t fphint_handle;
133 static dissector_handle_t mtp2_handle;
134 
135 static dissector_table_t meta_dissector_table;
136 
137 static const value_string meta_schema_vals[] = {
138     { META_SCHEMA_PCAP,     "PCAP" },
139     { META_SCHEMA_DXT,      "DXT" },
140     { 0, NULL }
141 };
142 
143 static const value_string meta_proto_vals[] = {
144     { META_PROTO_DXT_ETHERNET,      "Ethernet without FCS" },
145     { META_PROTO_DXT_ETHERNET_CRC,  "Ethernet with FCS" },
146     { META_PROTO_DXT_ATM,           "ATM" },
147     { META_PROTO_DXT_ERF_AAL5,      "ERF AAL5" },
148     /* XXX: META_PROTO_DXT_M3UA ? */
149     /* XXX: META_PROTO_DXT_NBAP ? */
150     { META_PROTO_DXT_ATM_AAL2,      "ATM AAL2" },
151     { META_PROTO_DXT_FP_HINT,       "FP Hint" },
152     { META_PROTO_DXT_HDLC,          "HDLC" },
153     { META_PROTO_DXT_CONTAINER,     "DXT CONTAINER" },
154     { META_PROTO_DXT_FP_CAPTURE,    "FP CAPTURE" },
155     { META_PROTO_DXT_UTRAN_CAPSULE, "UTRAN CAPSULE" },
156     { 0, NULL }
157 };
158 static value_string_ext meta_proto_vals_ext = VALUE_STRING_EXT_INIT(meta_proto_vals);
159 
160 static const value_string meta_type_vals[] = {
161     { META_TYPE_NONE,       "NONE" },
162     { META_TYPE_BOOLEAN,    "BOOLEAN" },
163     { META_TYPE_UINT8,      "UINT8" },
164     { META_TYPE_UINT16,     "UINT16" },
165     { META_TYPE_UINT32,     "UINT32" },
166     { META_TYPE_UINT64,     "UINT64" },
167     { META_TYPE_STRING,     "STRING" },
168     { 0, NULL }
169 };
170 
171 /* TODO: this must be on a per-schema basis! */
172 static const value_string meta_id_vals[] = {
173     { META_ID_NULL,         "NULL" },
174     { META_ID_DIRECTION,    "Direction" },
175     { META_ID_SIGNALING,    "Signaling" },
176     { META_ID_INCOMPLETE,   "Incomplete" },
177     { META_ID_DECIPHERED,   "Deciphered" },
178     { META_ID_PAYLOADCUT,   "Payload cutted" },
179     { META_ID_TIMESTAMP64,  "Timestamp" },
180     { META_ID_AAL5PROTO,    "AAL5 Protocol Type" },
181     { META_ID_PHYLINKID,    "Physical Link ID" },
182     { META_ID_LOCALDEVID,   "Local Device ID" },
183     { META_ID_REMOTEDEVID,  "Remote Device ID" },
184     { META_ID_TAPGROUPID,   "Tap Group ID" },
185     { META_ID_IMSI,         "IMSI" },
186     { META_ID_IMEI,         "IMEI" },
187     { META_ID_CELL,         "Mobile Cell" },
188     { META_ID_TLLI,         "TLLI" },
189     { META_ID_NSAPI,        "NSAPI" },
190     { META_ID_APN,          "APN" },
191     { META_ID_RAT,          "RAT" },
192     { META_ID_CALLING,      "Calling Station ID" },
193     { META_ID_CALLED,       "Called Station ID" },
194     { 0, NULL }
195 };
196 static value_string_ext meta_id_vals_ext = VALUE_STRING_EXT_INIT(meta_id_vals);
197 
198 #define META_AAL5PROTO_MTP3     2
199 #define META_AAL5PROTO_NS       3
200 #define META_AAL5PROTO_ALCAP    5
201 #define META_AAL5PROTO_NBAP     6
202 static const value_string meta_aal5proto_vals[] = {
203     { META_AAL5PROTO_MTP3,  "SSCOP MTP3" },
204     { META_AAL5PROTO_ALCAP, "SSCOP ALCAP" },
205     { META_AAL5PROTO_NBAP,  "SSCOP NBAP" },
206     { META_AAL5PROTO_NS,    "GPRS NS" },
207     { 0, NULL }
208 };
209 
210 static const value_string meta_direction_vals[] = {
211     { 0,    "Up" },
212     { 1,    "Down" },
213     { 0,    NULL }
214 };
215 
216 static guint16 skip_item(proto_tree *meta_tree, tvbuff_t *tvb, packet_info *pinfo _U_, guint16 offs)
217 {
218     guint16     id;
219     guint8      type;
220     guint16     len, aligned_len, total_len;
221     proto_tree *item_tree;
222     proto_item *subti;
223 
224     id          = tvb_get_letohs(tvb, offs); offs += 2;
225     type        = tvb_get_guint8(tvb, offs); offs++;
226     len         = tvb_get_guint8(tvb, offs); offs++;
227     aligned_len = (len + 3) & 0xfffc;
228     total_len   = aligned_len + 4; /* 4: id, type, len fields */
229 
230     subti = proto_tree_add_item(meta_tree, hf_meta_item, tvb, offs - 4,
231         aligned_len + 4, ENC_NA);
232     item_tree = proto_item_add_subtree(subti, ett_meta_item);
233     proto_tree_add_uint(item_tree, hf_meta_item_id, tvb, offs - 4, 2, id);
234     proto_tree_add_uint(item_tree, hf_meta_item_type, tvb, offs - 2, 1, type);
235     proto_tree_add_uint(item_tree, hf_meta_item_len,
236         tvb, offs - 1, 1, len);
237     if (len > 0)
238         proto_tree_add_item(item_tree, hf_meta_item_data,
239             tvb, offs, len, ENC_NA);
240 
241     return total_len;
242 }
243 
244 /*
245 * offs: current offset in tvb
246 */
247 static guint16 evaluate_meta_item_pcap(proto_tree *meta_tree, tvbuff_t *tvb, packet_info *pinfo, guint16 offs)
248 {
249     guint16     id;
250     guint8      type;
251     guint16     len, aligned_len, total_len;
252     proto_tree *item_tree;
253     proto_item *subti;
254     /* field values */
255     guint8      dir;
256     guint64     ts;
257 
258     id          = tvb_get_letohs(tvb, offs); offs += 2;
259     type        = tvb_get_guint8(tvb, offs); offs++;
260     len         = tvb_get_guint8(tvb, offs); offs++;
261     aligned_len = (len + 3) & 0xfffc;
262     total_len   = aligned_len + 4; /* 4: id, type, len fields */
263 
264     switch (id) {
265         case META_ID_DIRECTION:
266             dir = tvb_get_guint8(tvb, offs);
267             pinfo->p2p_dir = dir == META_DIR_UP ? P2P_DIR_RECV : P2P_DIR_SENT;
268             proto_tree_add_uint(meta_tree, hf_meta_item_direction, tvb, offs, 1, dir);
269             break;
270         case META_ID_TIMESTAMP64:
271             ts = tvb_get_letoh64(tvb, offs);
272             proto_tree_add_uint64(meta_tree, hf_meta_item_ts, tvb, offs, 8, ts);
273             break;
274         case META_ID_SIGNALING:
275             proto_tree_add_boolean(meta_tree, hf_meta_item_signaling, tvb,
276                 offs, 0, 1);
277             break;
278         case META_ID_INCOMPLETE:
279             proto_tree_add_boolean(meta_tree, hf_meta_item_incomplete, tvb,
280                 offs, 0, 1);
281             break;
282         default:
283             subti = proto_tree_add_item(meta_tree, hf_meta_item, tvb, offs - 4,
284                 aligned_len + 4, ENC_NA);
285             item_tree = proto_item_add_subtree(subti, ett_meta_item);
286             proto_tree_add_uint(item_tree, hf_meta_item_id, tvb, offs - 4, 2, id);
287             proto_tree_add_uint(item_tree, hf_meta_item_type, tvb, offs - 2, 1, type);
288             proto_tree_add_uint(item_tree, hf_meta_item_len,
289                 tvb, offs - 1, 1, len);
290             if (len > 0)
291                 proto_tree_add_item(item_tree, hf_meta_item_data,
292                     tvb, offs, len, ENC_NA);
293     }
294     return total_len;
295 }
296 
297 /*
298 * offs: current offset in tvb
299 */
300 static guint16 evaluate_meta_item_dxt(proto_tree *meta_tree, tvbuff_t *tvb, packet_info *pinfo, guint16 offs, struct atm_phdr *atm_info)
301 {
302     guint16             id;
303     guint8              type;
304     guint16             len, aligned_len, total_len;
305     proto_tree         *item_tree;
306     proto_item         *subti;
307     /* field values */
308     guint8              dir, nsapi, rat, aal5proto;
309     guint16             phylinkid, localdevid, remotedevid, tapgroupid;
310     guint32             tlli;
311     guint64             ts, cell;
312     sscop_payload_info *p_sscop_info;
313     proto_item         *cell_item, *imsi_item, *imei_item;
314     proto_tree         *cell_tree, *imsi_tree, *imei_tree;
315 
316     id          = tvb_get_letohs(tvb, offs); offs += 2;
317     type        = tvb_get_guint8(tvb, offs); offs++;
318     len         = tvb_get_guint8(tvb, offs); offs++;
319     aligned_len = (len + 3) & 0xfffc;
320     total_len   = aligned_len + 4; /* 4: id, type, len fields */
321 
322     switch (id) {
323         case META_ID_DIRECTION:
324             dir = tvb_get_guint8(tvb, offs);
325             pinfo->p2p_dir = (dir == META_DIR_UP ? P2P_DIR_RECV : P2P_DIR_SENT);
326             proto_tree_add_uint(meta_tree, hf_meta_item_direction, tvb, offs, 1, dir);
327             break;
328         case META_ID_TIMESTAMP64:
329             ts = tvb_get_letoh64(tvb, offs);
330             proto_tree_add_uint64(meta_tree, hf_meta_item_ts, tvb, offs, 8, ts);
331             break;
332         case META_ID_PHYLINKID:
333             phylinkid = tvb_get_letohs(tvb, offs);
334             pinfo->link_number = phylinkid;
335             proto_tree_add_uint(meta_tree, hf_meta_item_phylinkid, tvb,
336                 offs, 2, phylinkid);
337             break;
338         case META_ID_NSAPI:
339             nsapi = tvb_get_guint8(tvb, offs);
340             proto_tree_add_uint(meta_tree, hf_meta_item_nsapi, tvb,
341                 offs, 1, nsapi);
342             break;
343         case META_ID_IMSI:
344             imsi_item = proto_tree_add_item(meta_tree, hf_meta_item_imsi_digits, tvb,
345                 offs, 8, ENC_BCD_DIGITS_0_9);
346             imsi_tree = proto_item_add_subtree(imsi_item, ett_meta_imsi);
347             proto_tree_add_item(imsi_tree, hf_meta_item_imsi_value,
348                 tvb, offs, 8, ENC_LITTLE_ENDIAN);
349             break;
350         case META_ID_IMEI:
351             imei_item = proto_tree_add_item(meta_tree, hf_meta_item_imei_digits, tvb,
352                 offs, 8, ENC_BCD_DIGITS_0_9);
353             imei_tree = proto_item_add_subtree(imei_item, ett_meta_imei);
354             proto_tree_add_item(imei_tree, hf_meta_item_imei_value,
355                 tvb, offs, 8, ENC_LITTLE_ENDIAN);
356             break;
357         case META_ID_APN:
358             proto_tree_add_item(meta_tree, hf_meta_item_apn, tvb,
359                 offs, len, ENC_ASCII|ENC_NA);
360             break;
361         case META_ID_RAT:
362             rat = tvb_get_guint8(tvb, offs);
363             proto_tree_add_uint(meta_tree, hf_meta_item_rat, tvb,
364                 offs, 1, rat);
365             break;
366         case META_ID_CELL:
367             cell = tvb_get_ntoh64(tvb, offs);
368             cell_item = proto_tree_add_uint64_format(meta_tree, hf_meta_item_cell,
369                                                      tvb, offs, 8, cell, "Mobile Cell");
370             cell_tree = proto_item_add_subtree(cell_item, ett_meta_cell);
371             de_gmm_rai(tvb, cell_tree, pinfo, offs, 8, NULL, 0);
372             de_cell_id(tvb, cell_tree, pinfo, offs + 6, 2, NULL, 0);
373             break;
374         case META_ID_SIGNALING:
375             proto_tree_add_boolean(meta_tree, hf_meta_item_signaling, tvb,
376                                    offs, 0, 1);
377             break;
378         case META_ID_INCOMPLETE:
379             proto_tree_add_boolean(meta_tree, hf_meta_item_incomplete, tvb,
380                 offs, 0, 1);
381             break;
382         case META_ID_DECIPHERED:
383             proto_tree_add_boolean(meta_tree, hf_meta_item_deciphered, tvb,
384                 offs, 0, 1);
385             break;
386         case META_ID_AAL5PROTO:
387             aal5proto    = tvb_get_guint8(tvb, offs);
388             p_sscop_info = (sscop_payload_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_sscop, 0);
389             if (!p_sscop_info) {
390                 p_sscop_info = wmem_new0(wmem_file_scope(), sscop_payload_info);
391                 p_add_proto_data(wmem_file_scope(), pinfo, proto_sscop, 0, p_sscop_info);
392             }
393             switch (aal5proto) {
394                 case META_AAL5PROTO_MTP3:
395                     p_sscop_info->subdissector = sscf_nni_handle;
396                     /* hint for ATM dissector that this frame contains SSCOP */
397                     memset(atm_info, 0, sizeof(*atm_info));
398                     atm_info->type = TRAF_SSCOP;
399                     break;
400                 case META_AAL5PROTO_ALCAP:
401                     p_sscop_info->subdissector = alcap_handle;
402                     break;
403                 case META_AAL5PROTO_NBAP:
404                     p_sscop_info->subdissector = nbap_handle;
405                     break;
406                 case META_AAL5PROTO_NS:
407                     /* hint for ATM dissector that this frame contains GPRS NS */
408                     memset(atm_info, 0, sizeof(*atm_info));
409                     atm_info->type = TRAF_GPRS_NS;
410                     break;
411                 /* TODO: check for additional protos on Iu 802 LLC/SNAP ... */
412                 default:
413                     /* TODO: add warning */
414                     p_remove_proto_data(wmem_file_scope(), pinfo, proto_sscop, 0);
415             }
416             proto_tree_add_uint(meta_tree, hf_meta_item_aal5proto, tvb,
417                 offs, 1, aal5proto);
418             break;
419         case META_ID_LOCALDEVID:
420             localdevid = tvb_get_letohs(tvb, offs);
421             proto_tree_add_uint(meta_tree, hf_meta_item_localdevid, tvb,
422                 offs, 2, localdevid);
423             break;
424         case META_ID_REMOTEDEVID:
425             remotedevid = tvb_get_letohs(tvb, offs);
426             proto_tree_add_uint(meta_tree, hf_meta_item_remotedevid, tvb,
427                 offs, 2, remotedevid);
428             break;
429         case META_ID_TAPGROUPID:
430             tapgroupid = tvb_get_letohs(tvb, offs);
431             proto_tree_add_uint(meta_tree, hf_meta_item_tapgroupid, tvb,
432                 offs, 2, tapgroupid);
433             break;
434         case META_ID_TLLI:
435             tlli = tvb_get_letohs(tvb, offs);
436             proto_tree_add_uint(meta_tree, hf_meta_item_tlli, tvb,
437                 offs, 4, tlli);
438             break;
439         case META_ID_CALLING:
440             proto_tree_add_item(meta_tree, hf_meta_item_calling, tvb,
441                 offs, len, ENC_ASCII|ENC_NA);
442             break;
443         case META_ID_CALLED:
444             proto_tree_add_item(meta_tree, hf_meta_item_called, tvb,
445                 offs, len, ENC_ASCII|ENC_NA);
446             break;
447         default:
448             subti = proto_tree_add_item(meta_tree, hf_meta_item, tvb, offs - 4,
449                 aligned_len + 4, ENC_NA);
450             item_tree = proto_item_add_subtree(subti, ett_meta_item);
451             proto_tree_add_uint(item_tree, hf_meta_item_id, tvb, offs - 4, 2, id);
452             proto_tree_add_uint(item_tree, hf_meta_item_type, tvb, offs - 2, 1, type);
453             proto_tree_add_uint(item_tree, hf_meta_item_len,
454                 tvb, offs - 1, 1, len);
455             if (len > 0)
456                 proto_tree_add_item(item_tree, hf_meta_item_data,
457                     tvb, offs, len, ENC_NA);
458     }
459     return total_len;
460 }
461 
462 /*
463  * offs: current offset within tvb
464  * header_length: length of meta header
465  */
466 static gint32 evaluate_meta_items(guint16 schema, tvbuff_t *tvb, packet_info *pinfo,
467     proto_tree *meta_tree, guint16 offs, gint32 header_length,
468     struct atm_phdr *atm_info)
469 {
470     gint16 item_len;
471     gint32 total_len = 0;
472 
473     while (total_len < header_length) {
474         switch (schema) {
475             case META_SCHEMA_DXT:
476                 item_len = evaluate_meta_item_dxt(meta_tree, tvb, pinfo, offs + total_len, atm_info);
477                 break;
478             case META_SCHEMA_PCAP:
479                 item_len = evaluate_meta_item_pcap(meta_tree, tvb, pinfo, offs + total_len);
480                 break;
481             default:
482                 item_len = skip_item(meta_tree, tvb, pinfo, offs + total_len);
483         }
484         if (item_len < 4) { /* 4 is the minimum length of an item: id + type + length field */
485             expert_add_info_format(pinfo, meta_tree, &ei_meta_malformed,
486                 "Malformed Packet %s (wrong item encoding)", pinfo->current_proto);
487             return -1;
488         }
489         total_len += item_len;
490     }
491     return total_len;
492 }
493 
494 static int
495 dissect_meta(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
496 {
497 #define META_HEADER_SIZE 8
498     guint16             schema, proto, hdrlen, reserved;
499     gint32              item_len;
500     guint32             aal2_ext, atm_hdr;
501     proto_tree         *meta_tree      = NULL;
502     proto_item         *ti             = NULL;
503     tvbuff_t           *next_tvb       = NULL;
504     dissector_handle_t  next_dissector = data_handle;
505     void               *next_dissector_data = NULL;
506     struct atm_phdr     atm_info;
507 
508     col_set_str(pinfo->cinfo, COL_PROTOCOL, "META");
509 
510     schema   = tvb_get_letohs(tvb, 0);
511     hdrlen   = tvb_get_letohs(tvb, 2);
512     proto    = tvb_get_letohs(tvb, 4);
513     reserved = tvb_get_letohs(tvb, 6);
514 
515     if (tree) {
516         ti = proto_tree_add_item(tree, proto_meta, tvb, 0, hdrlen + 4, ENC_NA);
517         meta_tree = proto_item_add_subtree(ti, ett_meta);
518         proto_tree_add_uint(meta_tree, hf_meta_schema, tvb, 0, 2, schema);
519         proto_tree_add_uint(meta_tree, hf_meta_hdrlen, tvb, 2, 2, hdrlen);
520         proto_tree_add_uint(meta_tree, hf_meta_proto, tvb, 4, 2, proto);
521         proto_tree_add_uint(meta_tree, hf_meta_reserved, tvb, 6, 2, reserved);
522     }
523     item_len = evaluate_meta_items(schema, tvb, pinfo, meta_tree, META_HEADER_SIZE, hdrlen, &atm_info);
524 
525     if (item_len < 0) {
526         /* evaluate_meta_items signalled an error */
527         return META_HEADER_SIZE; /* stop parsing */
528     }
529 
530     if (hdrlen != item_len) {
531         expert_add_info(pinfo, ti, &ei_meta_invalid_header);
532         return META_HEADER_SIZE;
533     }
534 
535     /* find next subdissector based on the chosen schema */
536     switch (schema) {
537         case META_SCHEMA_PCAP:
538             /* TODO */
539             break;
540         case META_SCHEMA_DXT:
541             switch (proto) {
542                 case META_PROTO_DXT_ETHERNET:
543                     next_dissector = ethwithoutfcs_handle;
544                     break;
545                 case META_PROTO_DXT_ETHERNET_CRC:
546                     next_dissector = ethwithfcs_handle;
547                     break;
548                 case META_PROTO_DXT_FP_HINT:
549                     next_dissector = fphint_handle;
550                     break;
551                 case META_PROTO_DXT_ATM:
552                     memset(&atm_info, 0, sizeof atm_info);
553                     atm_info.aal  = AAL_OAMCELL;
554                     atm_info.type = TRAF_UNKNOWN;
555                     next_dissector = atm_untrunc_handle;
556                     next_dissector_data = &atm_info;
557                     break;
558                 case META_PROTO_DXT_ATM_AAL2:
559                     aal2_ext = tvb_get_ntohl(tvb, item_len + META_HEADER_SIZE); item_len += 4;
560                     atm_hdr  = tvb_get_ntohl(tvb, item_len + META_HEADER_SIZE); item_len += 4;
561                     memset(&atm_info, 0, sizeof(atm_info));
562                     atm_info.aal = AAL_2;
563                     /* atm_info.flags = pinfo->p2p_dir; */
564                     atm_info.vpi  = ((atm_hdr & 0x0ff00000) >> 20);
565                     atm_info.vci  = ((atm_hdr & 0x000ffff0) >>  4);
566                     atm_info.aal2_cid = aal2_ext & 0x000000ff;
567                     atm_info.type = TRAF_UMTS_FP;
568                     next_dissector = atm_untrunc_handle;
569                     next_dissector_data = &atm_info;
570                     break;
571                 case META_PROTO_DXT_ERF_AAL5:
572                     atm_hdr = tvb_get_ntohl(tvb, item_len + META_HEADER_SIZE); item_len += 4;
573                     atm_info.vpi = ((atm_hdr & 0x0ff00000) >> 20);
574                     atm_info.vci = ((atm_hdr & 0x000ffff0) >>  4);
575                     atm_info.aal = AAL_5;
576                     next_dissector = atm_untrunc_handle;
577                     next_dissector_data = &atm_info;
578                     break;
579                 case META_PROTO_DXT_HDLC:
580                     next_dissector = mtp2_handle;
581                     next_tvb = tvb_new_subset_length_caplen(tvb, item_len + META_HEADER_SIZE,
582                         tvb_reported_length(tvb)-item_len-META_HEADER_SIZE-2, -1);
583                     break;
584                 default:
585                     next_dissector =
586                         dissector_get_uint_handle(meta_dissector_table, proto);
587             }
588     }
589     if (!next_tvb)
590         next_tvb = tvb_new_subset_remaining(tvb, item_len + META_HEADER_SIZE);
591 
592     call_dissector_with_data(next_dissector, next_tvb, pinfo, tree,
593                              next_dissector_data);
594     return tvb_captured_length(tvb);
595 }
596 
597 void
598 proto_register_meta(void)
599 {
600     static hf_register_info hf[] = {
601         /* metadata header */
602         { &hf_meta_schema,
603           { "Schema", "meta.schema",
604             FT_UINT16, BASE_DEC, VALS(meta_schema_vals), 0,
605             NULL, HFILL }
606         },
607         { &hf_meta_hdrlen,
608           { "Header Length", "meta.hdrlen",
609             FT_UINT16, BASE_DEC, NULL, 0,
610             NULL, HFILL }
611         },
612         { &hf_meta_proto,
613           { "Protocol", "meta.proto",
614             FT_UINT16, BASE_DEC | BASE_EXT_STRING, &meta_proto_vals_ext, 0,
615             NULL, HFILL }
616         },
617         { &hf_meta_reserved,
618           { "Reserved", "meta.reserved",
619             FT_UINT16, BASE_HEX, NULL, 0,
620             NULL, HFILL }
621         },
622 
623         /* general meta item */
624         { &hf_meta_item,
625           { "Unknown Item", "meta.item",
626             FT_NONE, BASE_NONE, NULL, 0,
627             NULL, HFILL }
628         },
629         { &hf_meta_item_id,
630           { "Item ID", "meta.item.id",
631             FT_UINT16, BASE_HEX | BASE_EXT_STRING, &meta_id_vals_ext, 0x0,
632             NULL, HFILL }
633         },
634         { &hf_meta_item_type,
635           { "Item Type", "meta.item.type",
636             FT_UINT8, BASE_HEX, VALS(meta_type_vals), 0x0,
637             NULL, HFILL }
638         },
639         { &hf_meta_item_len,
640           { "Item Length", "meta.item.len",
641             FT_UINT8, BASE_DEC, NULL, 0,
642             NULL, HFILL }
643         },
644         { &hf_meta_item_data,
645           { "Item Data", "meta.item.data",
646             FT_BYTES, BASE_NONE, NULL, 0x0,
647             NULL, HFILL }
648         },
649 
650         /* specific meta items */
651         { &hf_meta_item_direction,
652           { "Direction", "meta.direction",
653             FT_UINT8, BASE_DEC, VALS(meta_direction_vals), 0,
654             NULL, HFILL }
655         },
656         { &hf_meta_item_ts,
657           { "Timestamp", "meta.timestamp",
658             FT_UINT64, BASE_DEC, NULL, 0,
659             NULL, HFILL }
660         },
661         { &hf_meta_item_phylinkid,
662           { "Physical Link ID", "meta.phylinkid",
663             FT_UINT16, BASE_DEC, NULL, 0,
664             NULL, HFILL }
665         },
666         { &hf_meta_item_nsapi,
667           { "NSAPI", "meta.nsapi",
668             FT_UINT8, BASE_DEC, NULL, 0,
669             NULL, HFILL }
670         },
671         { &hf_meta_item_imsi_digits,
672           { "IMSI digits", "meta.imsi_digits",
673             FT_STRING, BASE_NONE, NULL, 0,
674             NULL, HFILL }
675         },
676         { &hf_meta_item_imsi_value,
677           { "IMSI value", "meta.imsi_value",
678             FT_UINT64, BASE_HEX, NULL, 0,
679             NULL, HFILL }
680         },
681         { &hf_meta_item_imei_digits,
682           { "IMEI digits", "meta.imei_digits",
683             FT_STRING, BASE_NONE, NULL, 0,
684             NULL, HFILL }
685         },
686         { &hf_meta_item_imei_value,
687           { "IMEI value", "meta.imei_value",
688             FT_UINT64, BASE_HEX, NULL, 0,
689             NULL, HFILL }
690         },
691         { &hf_meta_item_signaling,
692           { "Signaling", "meta.signaling",
693             FT_BOOLEAN, BASE_NONE, NULL, 0,
694             NULL, HFILL }
695         },
696         { &hf_meta_item_incomplete,
697           { "Incomplete", "meta.incomplete",
698             FT_BOOLEAN, BASE_NONE, NULL, 0,
699             NULL, HFILL }
700         },
701         { &hf_meta_item_deciphered,
702           { "Deciphered", "meta.deciphered",
703             FT_BOOLEAN, BASE_NONE, NULL, 0,
704             NULL, HFILL }
705         },
706         { &hf_meta_item_apn,
707           { "APN", "meta.apn",
708             FT_STRINGZ, BASE_NONE, NULL, 0,
709             NULL, HFILL }
710         },
711         { &hf_meta_item_rat,
712           { "RAT", "meta.rat",
713             FT_UINT8, BASE_DEC, NULL, 0,
714             NULL, HFILL }
715         },
716         { &hf_meta_item_aal5proto,
717           { "AAL5 Protocol Type", "meta.aal5proto",
718             FT_UINT8, BASE_DEC, VALS(meta_aal5proto_vals), 0,
719             NULL, HFILL }
720         },
721         { &hf_meta_item_cell,
722           { "Mobile Cell", "meta.cell",
723             FT_UINT64, BASE_HEX, NULL, 0,
724             NULL, HFILL }
725         },
726 
727         { &hf_meta_item_localdevid,
728           { "Local Device ID", "meta.localdevid",
729             FT_UINT16, BASE_DEC, NULL, 0,
730             NULL, HFILL }
731         },
732         { &hf_meta_item_remotedevid,
733           { "Remote Device ID", "meta.remotedevid",
734             FT_UINT16, BASE_DEC, NULL, 0,
735             NULL, HFILL }
736         },
737         { &hf_meta_item_tapgroupid,
738           { "Tap Group ID", "meta.tapgroupid",
739             FT_UINT16, BASE_DEC, NULL, 0,
740             NULL, HFILL }
741         },
742         { &hf_meta_item_tlli,
743           { "TLLI", "meta.tlli",
744             FT_UINT32, BASE_DEC, NULL, 0,
745             NULL, HFILL }
746         },
747         { &hf_meta_item_calling,
748           { "Calling Station ID", "meta.calling",
749             FT_STRINGZ, BASE_NONE, NULL, 0,
750             NULL, HFILL }
751         },
752         { &hf_meta_item_called,
753           { "Called Station ID", "meta.called",
754             FT_STRINGZ, BASE_NONE, NULL, 0,
755             NULL, HFILL }
756         },
757     };
758 
759     static gint *ett[] = {
760         &ett_meta,
761         &ett_meta_item,
762         &ett_meta_cell,
763         &ett_meta_imsi,
764         &ett_meta_imei
765     };
766 
767     static ei_register_info ei[] = {
768         { &ei_meta_malformed, { "meta.malformed", PI_MALFORMED, PI_ERROR, "Malformed data", EXPFILL }},
769         { &ei_meta_invalid_header, { "meta.invalid_header_length", PI_MALFORMED, PI_ERROR, "Invalid Header Length", EXPFILL }},
770     };
771 
772     expert_module_t* expert_meta;
773 
774     proto_meta = proto_register_protocol("Metadata", "META", "meta");
775     register_dissector("meta", dissect_meta, proto_meta);
776 
777     proto_register_field_array(proto_meta, hf, array_length(hf));
778     proto_register_subtree_array(ett, array_length(ett));
779     expert_meta = expert_register_protocol(proto_meta);
780     expert_register_field_array(expert_meta, ei, array_length(ei));
781 
782     meta_dissector_table = register_dissector_table("meta.proto",
783             "META protocol", proto_meta, FT_UINT16, BASE_DEC);
784 }
785 
786 void
787 proto_reg_handoff_meta(void)
788 {
789 #if 0   /* enable once WTAP_ENCAP_META exists */
790     dissector_handle_t meta_handle;
791 
792     meta_handle          = find_dissector("meta");
793     dissector_add_uint("wtap_encap", WTAP_ENCAP_META, meta_handle);
794 #endif
795     data_handle          = find_dissector("data");
796     alcap_handle         = find_dissector_add_dependency("alcap", proto_meta);
797     atm_untrunc_handle   = find_dissector_add_dependency("atm_untruncated", proto_meta);
798     nbap_handle          = find_dissector_add_dependency("nbap", proto_meta);
799     sscf_nni_handle      = find_dissector_add_dependency("sscf-nni", proto_meta);
800     ethwithfcs_handle    = find_dissector_add_dependency("eth_withfcs", proto_meta);
801     ethwithoutfcs_handle = find_dissector_add_dependency("eth_withoutfcs", proto_meta);
802     fphint_handle        = find_dissector_add_dependency("fp_hint", proto_meta);
803     mtp2_handle          = find_dissector_add_dependency("mtp2", proto_meta);
804 }
805 
806 /*
807  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
808  *
809  * Local variables:
810  * c-basic-offset: 4
811  * tab-width: 8
812  * indent-tabs-mode: nil
813  * End:
814  *
815  * vi: set shiftwidth=4 tabstop=8 expandtab:
816  * :indentSize=4:tabSize=8:noTabs=true:
817  */
818