/src/wireshark/epan/dissectors/packet-meta.c
Line | Count | Source (jump to first uncovered line) |
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 | 0 | #define META_SCHEMA_PCAP 1 |
25 | 0 | #define META_SCHEMA_DXT 2 |
26 | | |
27 | | /* protocols */ |
28 | 0 | #define META_PROTO_DXT_ETHERNET 1 |
29 | 0 | #define META_PROTO_DXT_ETHERNET_CRC 36 |
30 | 0 | #define META_PROTO_DXT_ATM 41 |
31 | 0 | #define META_PROTO_DXT_ERF_AAL5 49 |
32 | | #define META_PROTO_DXT_M3UA 61 |
33 | | #define META_PROTO_DXT_NBAP 69 |
34 | 0 | #define META_PROTO_DXT_ATM_AAL2 76 |
35 | 0 | #define META_PROTO_DXT_FP_HINT 82 |
36 | 0 | #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 | 0 | #define META_ID_DIRECTION 1 |
53 | 0 | #define META_ID_SIGNALING 2 |
54 | 0 | #define META_ID_INCOMPLETE 3 |
55 | 0 | #define META_ID_DECIPHERED 4 |
56 | | #define META_ID_PAYLOADCUT 5 |
57 | 0 | #define META_ID_TIMESTAMP64 6 |
58 | 0 | #define META_ID_AAL5PROTO 7 |
59 | 0 | #define META_ID_PHYLINKID 256 |
60 | 0 | #define META_ID_LOCALDEVID 257 |
61 | 0 | #define META_ID_REMOTEDEVID 258 |
62 | 0 | #define META_ID_TAPGROUPID 259 |
63 | 0 | #define META_ID_IMSI 1024 |
64 | 0 | #define META_ID_IMEI 1025 |
65 | 0 | #define META_ID_CELL 1026 |
66 | 0 | #define META_ID_TLLI 1027 |
67 | 0 | #define META_ID_NSAPI 1028 |
68 | 0 | #define META_ID_APN 1029 |
69 | 0 | #define META_ID_RAT 1030 |
70 | 0 | #define META_ID_CALLING 1031 |
71 | 0 | #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; |
79 | | extern int proto_sscop; |
80 | | |
81 | | /* fields */ |
82 | | static int hf_meta_schema; |
83 | | static int hf_meta_hdrlen; |
84 | | static int hf_meta_proto; |
85 | | static int hf_meta_reserved; |
86 | | static int hf_meta_item; |
87 | | static int hf_meta_item_id; |
88 | | static int hf_meta_item_type; |
89 | | static int hf_meta_item_len; |
90 | | static int hf_meta_item_data; |
91 | | /* specific fields */ |
92 | | static int hf_meta_item_direction; |
93 | | static int hf_meta_item_ts; |
94 | | static int hf_meta_item_phylinkid; |
95 | | static int hf_meta_item_nsapi; |
96 | | static int hf_meta_item_imsi_value; |
97 | | static int hf_meta_item_imsi_digits; |
98 | | static int hf_meta_item_imei_value; |
99 | | static int hf_meta_item_imei_digits; |
100 | | static int hf_meta_item_signaling; |
101 | | static int hf_meta_item_incomplete; |
102 | | static int hf_meta_item_deciphered; |
103 | | static int hf_meta_item_apn; |
104 | | static int hf_meta_item_rat; |
105 | | static int hf_meta_item_aal5proto; |
106 | | static int hf_meta_item_cell; |
107 | | static int hf_meta_item_localdevid; |
108 | | static int hf_meta_item_remotedevid; |
109 | | static int hf_meta_item_tapgroupid; |
110 | | static int hf_meta_item_tlli; |
111 | | static int hf_meta_item_calling; |
112 | | static int hf_meta_item_called; |
113 | | |
114 | | /* subtrees */ |
115 | | static int ett_meta; |
116 | | static int ett_meta_item; |
117 | | static int ett_meta_cell; |
118 | | static int ett_meta_imsi; |
119 | | static int ett_meta_imei; |
120 | | |
121 | | static expert_field ei_meta_malformed; |
122 | | static expert_field ei_meta_invalid_header; |
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 | 0 | #define META_AAL5PROTO_MTP3 2 |
199 | 0 | #define META_AAL5PROTO_NS 3 |
200 | 0 | #define META_AAL5PROTO_ALCAP 5 |
201 | 0 | #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 uint16_t skip_item(proto_tree *meta_tree, tvbuff_t *tvb, packet_info *pinfo _U_, uint16_t offs) |
217 | 0 | { |
218 | 0 | uint16_t id; |
219 | 0 | uint8_t type; |
220 | 0 | uint16_t len, aligned_len, total_len; |
221 | 0 | proto_tree *item_tree; |
222 | 0 | proto_item *subti; |
223 | |
|
224 | 0 | id = tvb_get_letohs(tvb, offs); offs += 2; |
225 | 0 | type = tvb_get_uint8(tvb, offs); offs++; |
226 | 0 | len = tvb_get_uint8(tvb, offs); offs++; |
227 | 0 | aligned_len = (len + 3) & 0xfffc; |
228 | 0 | total_len = aligned_len + 4; /* 4: id, type, len fields */ |
229 | |
|
230 | 0 | subti = proto_tree_add_item(meta_tree, hf_meta_item, tvb, offs - 4, |
231 | 0 | aligned_len + 4, ENC_NA); |
232 | 0 | item_tree = proto_item_add_subtree(subti, ett_meta_item); |
233 | 0 | proto_tree_add_uint(item_tree, hf_meta_item_id, tvb, offs - 4, 2, id); |
234 | 0 | proto_tree_add_uint(item_tree, hf_meta_item_type, tvb, offs - 2, 1, type); |
235 | 0 | proto_tree_add_uint(item_tree, hf_meta_item_len, |
236 | 0 | tvb, offs - 1, 1, len); |
237 | 0 | if (len > 0) |
238 | 0 | proto_tree_add_item(item_tree, hf_meta_item_data, |
239 | 0 | tvb, offs, len, ENC_NA); |
240 | |
|
241 | 0 | return total_len; |
242 | 0 | } |
243 | | |
244 | | /* |
245 | | * offs: current offset in tvb |
246 | | */ |
247 | | static uint16_t evaluate_meta_item_pcap(proto_tree *meta_tree, tvbuff_t *tvb, packet_info *pinfo, uint16_t offs) |
248 | 0 | { |
249 | 0 | uint16_t id; |
250 | 0 | uint8_t type; |
251 | 0 | uint16_t len, aligned_len, total_len; |
252 | 0 | proto_tree *item_tree; |
253 | 0 | proto_item *subti; |
254 | | /* field values */ |
255 | 0 | uint8_t dir; |
256 | 0 | uint64_t ts; |
257 | |
|
258 | 0 | id = tvb_get_letohs(tvb, offs); offs += 2; |
259 | 0 | type = tvb_get_uint8(tvb, offs); offs++; |
260 | 0 | len = tvb_get_uint8(tvb, offs); offs++; |
261 | 0 | aligned_len = (len + 3) & 0xfffc; |
262 | 0 | total_len = aligned_len + 4; /* 4: id, type, len fields */ |
263 | |
|
264 | 0 | switch (id) { |
265 | 0 | case META_ID_DIRECTION: |
266 | 0 | dir = tvb_get_uint8(tvb, offs); |
267 | 0 | pinfo->p2p_dir = dir == META_DIR_UP ? P2P_DIR_RECV : P2P_DIR_SENT; |
268 | 0 | proto_tree_add_uint(meta_tree, hf_meta_item_direction, tvb, offs, 1, dir); |
269 | 0 | break; |
270 | 0 | case META_ID_TIMESTAMP64: |
271 | 0 | ts = tvb_get_letoh64(tvb, offs); |
272 | 0 | proto_tree_add_uint64(meta_tree, hf_meta_item_ts, tvb, offs, 8, ts); |
273 | 0 | break; |
274 | 0 | case META_ID_SIGNALING: |
275 | 0 | proto_tree_add_boolean(meta_tree, hf_meta_item_signaling, tvb, |
276 | 0 | offs, 0, 1); |
277 | 0 | break; |
278 | 0 | case META_ID_INCOMPLETE: |
279 | 0 | proto_tree_add_boolean(meta_tree, hf_meta_item_incomplete, tvb, |
280 | 0 | offs, 0, 1); |
281 | 0 | break; |
282 | 0 | default: |
283 | 0 | subti = proto_tree_add_item(meta_tree, hf_meta_item, tvb, offs - 4, |
284 | 0 | aligned_len + 4, ENC_NA); |
285 | 0 | item_tree = proto_item_add_subtree(subti, ett_meta_item); |
286 | 0 | proto_tree_add_uint(item_tree, hf_meta_item_id, tvb, offs - 4, 2, id); |
287 | 0 | proto_tree_add_uint(item_tree, hf_meta_item_type, tvb, offs - 2, 1, type); |
288 | 0 | proto_tree_add_uint(item_tree, hf_meta_item_len, |
289 | 0 | tvb, offs - 1, 1, len); |
290 | 0 | if (len > 0) |
291 | 0 | proto_tree_add_item(item_tree, hf_meta_item_data, |
292 | 0 | tvb, offs, len, ENC_NA); |
293 | 0 | } |
294 | 0 | return total_len; |
295 | 0 | } |
296 | | |
297 | | /* |
298 | | * offs: current offset in tvb |
299 | | */ |
300 | | static uint16_t evaluate_meta_item_dxt(proto_tree *meta_tree, tvbuff_t *tvb, packet_info *pinfo, uint16_t offs, struct atm_phdr *atm_info) |
301 | 0 | { |
302 | 0 | uint16_t id; |
303 | 0 | uint8_t type; |
304 | 0 | uint16_t len, aligned_len, total_len; |
305 | 0 | proto_tree *item_tree; |
306 | 0 | proto_item *subti; |
307 | | /* field values */ |
308 | 0 | uint8_t dir, nsapi, rat, aal5proto; |
309 | 0 | uint16_t phylinkid, localdevid, remotedevid, tapgroupid; |
310 | 0 | uint32_t tlli; |
311 | 0 | uint64_t ts, cell; |
312 | 0 | sscop_payload_info *p_sscop_info; |
313 | 0 | proto_item *cell_item, *imsi_item, *imei_item; |
314 | 0 | proto_tree *cell_tree, *imsi_tree, *imei_tree; |
315 | |
|
316 | 0 | id = tvb_get_letohs(tvb, offs); offs += 2; |
317 | 0 | type = tvb_get_uint8(tvb, offs); offs++; |
318 | 0 | len = tvb_get_uint8(tvb, offs); offs++; |
319 | 0 | aligned_len = (len + 3) & 0xfffc; |
320 | 0 | total_len = aligned_len + 4; /* 4: id, type, len fields */ |
321 | |
|
322 | 0 | switch (id) { |
323 | 0 | case META_ID_DIRECTION: |
324 | 0 | dir = tvb_get_uint8(tvb, offs); |
325 | 0 | pinfo->p2p_dir = (dir == META_DIR_UP ? P2P_DIR_RECV : P2P_DIR_SENT); |
326 | 0 | proto_tree_add_uint(meta_tree, hf_meta_item_direction, tvb, offs, 1, dir); |
327 | 0 | break; |
328 | 0 | case META_ID_TIMESTAMP64: |
329 | 0 | ts = tvb_get_letoh64(tvb, offs); |
330 | 0 | proto_tree_add_uint64(meta_tree, hf_meta_item_ts, tvb, offs, 8, ts); |
331 | 0 | break; |
332 | 0 | case META_ID_PHYLINKID: |
333 | 0 | phylinkid = tvb_get_letohs(tvb, offs); |
334 | 0 | pinfo->link_number = phylinkid; |
335 | 0 | proto_tree_add_uint(meta_tree, hf_meta_item_phylinkid, tvb, |
336 | 0 | offs, 2, phylinkid); |
337 | 0 | break; |
338 | 0 | case META_ID_NSAPI: |
339 | 0 | nsapi = tvb_get_uint8(tvb, offs); |
340 | 0 | proto_tree_add_uint(meta_tree, hf_meta_item_nsapi, tvb, |
341 | 0 | offs, 1, nsapi); |
342 | 0 | break; |
343 | 0 | case META_ID_IMSI: |
344 | 0 | imsi_item = proto_tree_add_item(meta_tree, hf_meta_item_imsi_digits, tvb, |
345 | 0 | offs, 8, ENC_BCD_DIGITS_0_9|ENC_LITTLE_ENDIAN); |
346 | 0 | imsi_tree = proto_item_add_subtree(imsi_item, ett_meta_imsi); |
347 | 0 | proto_tree_add_item(imsi_tree, hf_meta_item_imsi_value, |
348 | 0 | tvb, offs, 8, ENC_LITTLE_ENDIAN); |
349 | 0 | break; |
350 | 0 | case META_ID_IMEI: |
351 | 0 | imei_item = proto_tree_add_item(meta_tree, hf_meta_item_imei_digits, tvb, |
352 | 0 | offs, 8, ENC_BCD_DIGITS_0_9|ENC_LITTLE_ENDIAN); |
353 | 0 | imei_tree = proto_item_add_subtree(imei_item, ett_meta_imei); |
354 | 0 | proto_tree_add_item(imei_tree, hf_meta_item_imei_value, |
355 | 0 | tvb, offs, 8, ENC_LITTLE_ENDIAN); |
356 | 0 | break; |
357 | 0 | case META_ID_APN: |
358 | 0 | proto_tree_add_item(meta_tree, hf_meta_item_apn, tvb, |
359 | 0 | offs, len, ENC_ASCII); |
360 | 0 | break; |
361 | 0 | case META_ID_RAT: |
362 | 0 | rat = tvb_get_uint8(tvb, offs); |
363 | 0 | proto_tree_add_uint(meta_tree, hf_meta_item_rat, tvb, |
364 | 0 | offs, 1, rat); |
365 | 0 | break; |
366 | 0 | case META_ID_CELL: |
367 | 0 | cell = tvb_get_ntoh64(tvb, offs); |
368 | 0 | cell_item = proto_tree_add_uint64_format(meta_tree, hf_meta_item_cell, |
369 | 0 | tvb, offs, 8, cell, "Mobile Cell"); |
370 | 0 | cell_tree = proto_item_add_subtree(cell_item, ett_meta_cell); |
371 | 0 | de_gmm_rai(tvb, cell_tree, pinfo, offs, 8, NULL, 0); |
372 | 0 | de_cell_id(tvb, cell_tree, pinfo, offs + 6, 2, NULL, 0); |
373 | 0 | break; |
374 | 0 | case META_ID_SIGNALING: |
375 | 0 | proto_tree_add_boolean(meta_tree, hf_meta_item_signaling, tvb, |
376 | 0 | offs, 0, 1); |
377 | 0 | break; |
378 | 0 | case META_ID_INCOMPLETE: |
379 | 0 | proto_tree_add_boolean(meta_tree, hf_meta_item_incomplete, tvb, |
380 | 0 | offs, 0, 1); |
381 | 0 | break; |
382 | 0 | case META_ID_DECIPHERED: |
383 | 0 | proto_tree_add_boolean(meta_tree, hf_meta_item_deciphered, tvb, |
384 | 0 | offs, 0, 1); |
385 | 0 | break; |
386 | 0 | case META_ID_AAL5PROTO: |
387 | 0 | aal5proto = tvb_get_uint8(tvb, offs); |
388 | 0 | p_sscop_info = (sscop_payload_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_sscop, 0); |
389 | 0 | if (!p_sscop_info) { |
390 | 0 | p_sscop_info = wmem_new0(wmem_file_scope(), sscop_payload_info); |
391 | 0 | p_add_proto_data(wmem_file_scope(), pinfo, proto_sscop, 0, p_sscop_info); |
392 | 0 | } |
393 | 0 | switch (aal5proto) { |
394 | 0 | case META_AAL5PROTO_MTP3: |
395 | 0 | p_sscop_info->subdissector = sscf_nni_handle; |
396 | | /* hint for ATM dissector that this frame contains SSCOP */ |
397 | 0 | memset(atm_info, 0, sizeof(*atm_info)); |
398 | 0 | atm_info->type = TRAF_SSCOP; |
399 | 0 | break; |
400 | 0 | case META_AAL5PROTO_ALCAP: |
401 | 0 | p_sscop_info->subdissector = alcap_handle; |
402 | 0 | break; |
403 | 0 | case META_AAL5PROTO_NBAP: |
404 | 0 | p_sscop_info->subdissector = nbap_handle; |
405 | 0 | break; |
406 | 0 | case META_AAL5PROTO_NS: |
407 | | /* hint for ATM dissector that this frame contains GPRS NS */ |
408 | 0 | memset(atm_info, 0, sizeof(*atm_info)); |
409 | 0 | atm_info->type = TRAF_GPRS_NS; |
410 | 0 | break; |
411 | | /* TODO: check for additional protos on Iu 802 LLC/SNAP ... */ |
412 | 0 | default: |
413 | | /* TODO: add warning */ |
414 | 0 | p_remove_proto_data(wmem_file_scope(), pinfo, proto_sscop, 0); |
415 | 0 | } |
416 | 0 | proto_tree_add_uint(meta_tree, hf_meta_item_aal5proto, tvb, |
417 | 0 | offs, 1, aal5proto); |
418 | 0 | break; |
419 | 0 | case META_ID_LOCALDEVID: |
420 | 0 | localdevid = tvb_get_letohs(tvb, offs); |
421 | 0 | proto_tree_add_uint(meta_tree, hf_meta_item_localdevid, tvb, |
422 | 0 | offs, 2, localdevid); |
423 | 0 | break; |
424 | 0 | case META_ID_REMOTEDEVID: |
425 | 0 | remotedevid = tvb_get_letohs(tvb, offs); |
426 | 0 | proto_tree_add_uint(meta_tree, hf_meta_item_remotedevid, tvb, |
427 | 0 | offs, 2, remotedevid); |
428 | 0 | break; |
429 | 0 | case META_ID_TAPGROUPID: |
430 | 0 | tapgroupid = tvb_get_letohs(tvb, offs); |
431 | 0 | proto_tree_add_uint(meta_tree, hf_meta_item_tapgroupid, tvb, |
432 | 0 | offs, 2, tapgroupid); |
433 | 0 | break; |
434 | 0 | case META_ID_TLLI: |
435 | 0 | tlli = tvb_get_letohs(tvb, offs); |
436 | 0 | proto_tree_add_uint(meta_tree, hf_meta_item_tlli, tvb, |
437 | 0 | offs, 4, tlli); |
438 | 0 | break; |
439 | 0 | case META_ID_CALLING: |
440 | 0 | proto_tree_add_item(meta_tree, hf_meta_item_calling, tvb, |
441 | 0 | offs, len, ENC_ASCII); |
442 | 0 | break; |
443 | 0 | case META_ID_CALLED: |
444 | 0 | proto_tree_add_item(meta_tree, hf_meta_item_called, tvb, |
445 | 0 | offs, len, ENC_ASCII); |
446 | 0 | break; |
447 | 0 | default: |
448 | 0 | subti = proto_tree_add_item(meta_tree, hf_meta_item, tvb, offs - 4, |
449 | 0 | aligned_len + 4, ENC_NA); |
450 | 0 | item_tree = proto_item_add_subtree(subti, ett_meta_item); |
451 | 0 | proto_tree_add_uint(item_tree, hf_meta_item_id, tvb, offs - 4, 2, id); |
452 | 0 | proto_tree_add_uint(item_tree, hf_meta_item_type, tvb, offs - 2, 1, type); |
453 | 0 | proto_tree_add_uint(item_tree, hf_meta_item_len, |
454 | 0 | tvb, offs - 1, 1, len); |
455 | 0 | if (len > 0) |
456 | 0 | proto_tree_add_item(item_tree, hf_meta_item_data, |
457 | 0 | tvb, offs, len, ENC_NA); |
458 | 0 | } |
459 | 0 | return total_len; |
460 | 0 | } |
461 | | |
462 | | /* |
463 | | * offs: current offset within tvb |
464 | | * header_length: length of meta header |
465 | | */ |
466 | | static int32_t evaluate_meta_items(uint16_t schema, tvbuff_t *tvb, packet_info *pinfo, |
467 | | proto_tree *meta_tree, uint16_t offs, int32_t header_length, |
468 | | struct atm_phdr *atm_info) |
469 | 0 | { |
470 | 0 | int16_t item_len; |
471 | 0 | int32_t total_len = 0; |
472 | |
|
473 | 0 | while (total_len < header_length) { |
474 | 0 | switch (schema) { |
475 | 0 | case META_SCHEMA_DXT: |
476 | 0 | item_len = evaluate_meta_item_dxt(meta_tree, tvb, pinfo, offs + total_len, atm_info); |
477 | 0 | break; |
478 | 0 | case META_SCHEMA_PCAP: |
479 | 0 | item_len = evaluate_meta_item_pcap(meta_tree, tvb, pinfo, offs + total_len); |
480 | 0 | break; |
481 | 0 | default: |
482 | 0 | item_len = skip_item(meta_tree, tvb, pinfo, offs + total_len); |
483 | 0 | } |
484 | 0 | if (item_len < 4) { /* 4 is the minimum length of an item: id + type + length field */ |
485 | 0 | expert_add_info_format(pinfo, meta_tree, &ei_meta_malformed, |
486 | 0 | "Malformed Packet %s (wrong item encoding)", pinfo->current_proto); |
487 | 0 | return -1; |
488 | 0 | } |
489 | 0 | total_len += item_len; |
490 | 0 | } |
491 | 0 | return total_len; |
492 | 0 | } |
493 | | |
494 | | static int |
495 | | dissect_meta(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
496 | 0 | { |
497 | 0 | #define META_HEADER_SIZE 8 |
498 | 0 | uint16_t schema, proto, hdrlen, reserved; |
499 | 0 | int32_t item_len; |
500 | 0 | uint32_t aal2_ext, atm_hdr; |
501 | 0 | proto_tree *meta_tree = NULL; |
502 | 0 | proto_item *ti = NULL; |
503 | 0 | tvbuff_t *next_tvb = NULL; |
504 | 0 | dissector_handle_t next_dissector = data_handle; |
505 | 0 | void *next_dissector_data = NULL; |
506 | 0 | struct atm_phdr atm_info; |
507 | |
|
508 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "META"); |
509 | |
|
510 | 0 | schema = tvb_get_letohs(tvb, 0); |
511 | 0 | hdrlen = tvb_get_letohs(tvb, 2); |
512 | 0 | proto = tvb_get_letohs(tvb, 4); |
513 | 0 | reserved = tvb_get_letohs(tvb, 6); |
514 | |
|
515 | 0 | if (tree) { |
516 | 0 | ti = proto_tree_add_item(tree, proto_meta, tvb, 0, hdrlen + 4, ENC_NA); |
517 | 0 | meta_tree = proto_item_add_subtree(ti, ett_meta); |
518 | 0 | proto_tree_add_uint(meta_tree, hf_meta_schema, tvb, 0, 2, schema); |
519 | 0 | proto_tree_add_uint(meta_tree, hf_meta_hdrlen, tvb, 2, 2, hdrlen); |
520 | 0 | proto_tree_add_uint(meta_tree, hf_meta_proto, tvb, 4, 2, proto); |
521 | 0 | proto_tree_add_uint(meta_tree, hf_meta_reserved, tvb, 6, 2, reserved); |
522 | 0 | } |
523 | 0 | item_len = evaluate_meta_items(schema, tvb, pinfo, meta_tree, META_HEADER_SIZE, hdrlen, &atm_info); |
524 | |
|
525 | 0 | if (item_len < 0) { |
526 | | /* evaluate_meta_items signalled an error */ |
527 | 0 | return META_HEADER_SIZE; /* stop parsing */ |
528 | 0 | } |
529 | | |
530 | 0 | if (hdrlen != item_len) { |
531 | 0 | expert_add_info(pinfo, ti, &ei_meta_invalid_header); |
532 | 0 | return META_HEADER_SIZE; |
533 | 0 | } |
534 | | |
535 | | /* find next subdissector based on the chosen schema */ |
536 | 0 | switch (schema) { |
537 | 0 | case META_SCHEMA_PCAP: |
538 | | /* TODO */ |
539 | 0 | break; |
540 | 0 | case META_SCHEMA_DXT: |
541 | 0 | switch (proto) { |
542 | 0 | case META_PROTO_DXT_ETHERNET: |
543 | 0 | next_dissector = ethwithoutfcs_handle; |
544 | 0 | break; |
545 | 0 | case META_PROTO_DXT_ETHERNET_CRC: |
546 | 0 | next_dissector = ethwithfcs_handle; |
547 | 0 | break; |
548 | 0 | case META_PROTO_DXT_FP_HINT: |
549 | 0 | next_dissector = fphint_handle; |
550 | 0 | break; |
551 | 0 | case META_PROTO_DXT_ATM: |
552 | 0 | memset(&atm_info, 0, sizeof atm_info); |
553 | 0 | atm_info.aal = AAL_OAMCELL; |
554 | 0 | atm_info.type = TRAF_UNKNOWN; |
555 | 0 | next_dissector = atm_untrunc_handle; |
556 | 0 | next_dissector_data = &atm_info; |
557 | 0 | break; |
558 | 0 | case META_PROTO_DXT_ATM_AAL2: |
559 | 0 | aal2_ext = tvb_get_ntohl(tvb, item_len + META_HEADER_SIZE); item_len += 4; |
560 | 0 | atm_hdr = tvb_get_ntohl(tvb, item_len + META_HEADER_SIZE); item_len += 4; |
561 | 0 | memset(&atm_info, 0, sizeof(atm_info)); |
562 | 0 | atm_info.aal = AAL_2; |
563 | | /* atm_info.flags = pinfo->p2p_dir; */ |
564 | 0 | atm_info.vpi = ((atm_hdr & 0x0ff00000) >> 20); |
565 | 0 | atm_info.vci = ((atm_hdr & 0x000ffff0) >> 4); |
566 | 0 | atm_info.aal2_cid = aal2_ext & 0x000000ff; |
567 | 0 | atm_info.type = TRAF_UMTS_FP; |
568 | 0 | next_dissector = atm_untrunc_handle; |
569 | 0 | next_dissector_data = &atm_info; |
570 | 0 | break; |
571 | 0 | case META_PROTO_DXT_ERF_AAL5: |
572 | 0 | atm_hdr = tvb_get_ntohl(tvb, item_len + META_HEADER_SIZE); item_len += 4; |
573 | 0 | atm_info.vpi = ((atm_hdr & 0x0ff00000) >> 20); |
574 | 0 | atm_info.vci = ((atm_hdr & 0x000ffff0) >> 4); |
575 | 0 | atm_info.aal = AAL_5; |
576 | 0 | next_dissector = atm_untrunc_handle; |
577 | 0 | next_dissector_data = &atm_info; |
578 | 0 | break; |
579 | 0 | case META_PROTO_DXT_HDLC: |
580 | 0 | next_dissector = mtp2_handle; |
581 | 0 | next_tvb = tvb_new_subset_length_caplen(tvb, item_len + META_HEADER_SIZE, |
582 | 0 | tvb_reported_length(tvb)-item_len-META_HEADER_SIZE-2, -1); |
583 | 0 | break; |
584 | 0 | default: |
585 | 0 | next_dissector = |
586 | 0 | dissector_get_uint_handle(meta_dissector_table, proto); |
587 | 0 | } |
588 | 0 | } |
589 | 0 | if (!next_tvb) |
590 | 0 | next_tvb = tvb_new_subset_remaining(tvb, item_len + META_HEADER_SIZE); |
591 | |
|
592 | 0 | call_dissector_with_data(next_dissector, next_tvb, pinfo, tree, |
593 | 0 | next_dissector_data); |
594 | 0 | return tvb_captured_length(tvb); |
595 | 0 | } |
596 | | |
597 | | void |
598 | | proto_register_meta(void) |
599 | 14 | { |
600 | 14 | static hf_register_info hf[] = { |
601 | | /* metadata header */ |
602 | 14 | { &hf_meta_schema, |
603 | 14 | { "Schema", "meta.schema", |
604 | 14 | FT_UINT16, BASE_DEC, VALS(meta_schema_vals), 0, |
605 | 14 | NULL, HFILL } |
606 | 14 | }, |
607 | 14 | { &hf_meta_hdrlen, |
608 | 14 | { "Header Length", "meta.hdrlen", |
609 | 14 | FT_UINT16, BASE_DEC, NULL, 0, |
610 | 14 | NULL, HFILL } |
611 | 14 | }, |
612 | 14 | { &hf_meta_proto, |
613 | 14 | { "Protocol", "meta.proto", |
614 | 14 | FT_UINT16, BASE_DEC | BASE_EXT_STRING, &meta_proto_vals_ext, 0, |
615 | 14 | NULL, HFILL } |
616 | 14 | }, |
617 | 14 | { &hf_meta_reserved, |
618 | 14 | { "Reserved", "meta.reserved", |
619 | 14 | FT_UINT16, BASE_HEX, NULL, 0, |
620 | 14 | NULL, HFILL } |
621 | 14 | }, |
622 | | |
623 | | /* general meta item */ |
624 | 14 | { &hf_meta_item, |
625 | 14 | { "Unknown Item", "meta.item", |
626 | 14 | FT_NONE, BASE_NONE, NULL, 0, |
627 | 14 | NULL, HFILL } |
628 | 14 | }, |
629 | 14 | { &hf_meta_item_id, |
630 | 14 | { "Item ID", "meta.item.id", |
631 | 14 | FT_UINT16, BASE_HEX | BASE_EXT_STRING, &meta_id_vals_ext, 0x0, |
632 | 14 | NULL, HFILL } |
633 | 14 | }, |
634 | 14 | { &hf_meta_item_type, |
635 | 14 | { "Item Type", "meta.item.type", |
636 | 14 | FT_UINT8, BASE_HEX, VALS(meta_type_vals), 0x0, |
637 | 14 | NULL, HFILL } |
638 | 14 | }, |
639 | 14 | { &hf_meta_item_len, |
640 | 14 | { "Item Length", "meta.item.len", |
641 | 14 | FT_UINT8, BASE_DEC, NULL, 0, |
642 | 14 | NULL, HFILL } |
643 | 14 | }, |
644 | 14 | { &hf_meta_item_data, |
645 | 14 | { "Item Data", "meta.item.data", |
646 | 14 | FT_BYTES, BASE_NONE, NULL, 0x0, |
647 | 14 | NULL, HFILL } |
648 | 14 | }, |
649 | | |
650 | | /* specific meta items */ |
651 | 14 | { &hf_meta_item_direction, |
652 | 14 | { "Direction", "meta.direction", |
653 | 14 | FT_UINT8, BASE_DEC, VALS(meta_direction_vals), 0, |
654 | 14 | NULL, HFILL } |
655 | 14 | }, |
656 | 14 | { &hf_meta_item_ts, |
657 | 14 | { "Timestamp", "meta.timestamp", |
658 | 14 | FT_UINT64, BASE_DEC, NULL, 0, |
659 | 14 | NULL, HFILL } |
660 | 14 | }, |
661 | 14 | { &hf_meta_item_phylinkid, |
662 | 14 | { "Physical Link ID", "meta.phylinkid", |
663 | 14 | FT_UINT16, BASE_DEC, NULL, 0, |
664 | 14 | NULL, HFILL } |
665 | 14 | }, |
666 | 14 | { &hf_meta_item_nsapi, |
667 | 14 | { "NSAPI", "meta.nsapi", |
668 | 14 | FT_UINT8, BASE_DEC, NULL, 0, |
669 | 14 | NULL, HFILL } |
670 | 14 | }, |
671 | 14 | { &hf_meta_item_imsi_digits, |
672 | 14 | { "IMSI digits", "meta.imsi_digits", |
673 | 14 | FT_STRING, BASE_NONE, NULL, 0, |
674 | 14 | NULL, HFILL } |
675 | 14 | }, |
676 | 14 | { &hf_meta_item_imsi_value, |
677 | 14 | { "IMSI value", "meta.imsi_value", |
678 | 14 | FT_UINT64, BASE_HEX, NULL, 0, |
679 | 14 | NULL, HFILL } |
680 | 14 | }, |
681 | 14 | { &hf_meta_item_imei_digits, |
682 | 14 | { "IMEI digits", "meta.imei_digits", |
683 | 14 | FT_STRING, BASE_NONE, NULL, 0, |
684 | 14 | NULL, HFILL } |
685 | 14 | }, |
686 | 14 | { &hf_meta_item_imei_value, |
687 | 14 | { "IMEI value", "meta.imei_value", |
688 | 14 | FT_UINT64, BASE_HEX, NULL, 0, |
689 | 14 | NULL, HFILL } |
690 | 14 | }, |
691 | 14 | { &hf_meta_item_signaling, |
692 | 14 | { "Signaling", "meta.signaling", |
693 | 14 | FT_BOOLEAN, BASE_NONE, NULL, 0, |
694 | 14 | NULL, HFILL } |
695 | 14 | }, |
696 | 14 | { &hf_meta_item_incomplete, |
697 | 14 | { "Incomplete", "meta.incomplete", |
698 | 14 | FT_BOOLEAN, BASE_NONE, NULL, 0, |
699 | 14 | NULL, HFILL } |
700 | 14 | }, |
701 | 14 | { &hf_meta_item_deciphered, |
702 | 14 | { "Deciphered", "meta.deciphered", |
703 | 14 | FT_BOOLEAN, BASE_NONE, NULL, 0, |
704 | 14 | NULL, HFILL } |
705 | 14 | }, |
706 | 14 | { &hf_meta_item_apn, |
707 | 14 | { "APN", "meta.apn", |
708 | 14 | FT_STRINGZ, BASE_NONE, NULL, 0, |
709 | 14 | NULL, HFILL } |
710 | 14 | }, |
711 | 14 | { &hf_meta_item_rat, |
712 | 14 | { "RAT", "meta.rat", |
713 | 14 | FT_UINT8, BASE_DEC, NULL, 0, |
714 | 14 | NULL, HFILL } |
715 | 14 | }, |
716 | 14 | { &hf_meta_item_aal5proto, |
717 | 14 | { "AAL5 Protocol Type", "meta.aal5proto", |
718 | 14 | FT_UINT8, BASE_DEC, VALS(meta_aal5proto_vals), 0, |
719 | 14 | NULL, HFILL } |
720 | 14 | }, |
721 | 14 | { &hf_meta_item_cell, |
722 | 14 | { "Mobile Cell", "meta.cell", |
723 | 14 | FT_UINT64, BASE_HEX, NULL, 0, |
724 | 14 | NULL, HFILL } |
725 | 14 | }, |
726 | | |
727 | 14 | { &hf_meta_item_localdevid, |
728 | 14 | { "Local Device ID", "meta.localdevid", |
729 | 14 | FT_UINT16, BASE_DEC, NULL, 0, |
730 | 14 | NULL, HFILL } |
731 | 14 | }, |
732 | 14 | { &hf_meta_item_remotedevid, |
733 | 14 | { "Remote Device ID", "meta.remotedevid", |
734 | 14 | FT_UINT16, BASE_DEC, NULL, 0, |
735 | 14 | NULL, HFILL } |
736 | 14 | }, |
737 | 14 | { &hf_meta_item_tapgroupid, |
738 | 14 | { "Tap Group ID", "meta.tapgroupid", |
739 | 14 | FT_UINT16, BASE_DEC, NULL, 0, |
740 | 14 | NULL, HFILL } |
741 | 14 | }, |
742 | 14 | { &hf_meta_item_tlli, |
743 | 14 | { "TLLI", "meta.tlli", |
744 | 14 | FT_UINT32, BASE_DEC, NULL, 0, |
745 | 14 | NULL, HFILL } |
746 | 14 | }, |
747 | 14 | { &hf_meta_item_calling, |
748 | 14 | { "Calling Station ID", "meta.calling", |
749 | 14 | FT_STRINGZ, BASE_NONE, NULL, 0, |
750 | 14 | NULL, HFILL } |
751 | 14 | }, |
752 | 14 | { &hf_meta_item_called, |
753 | 14 | { "Called Station ID", "meta.called", |
754 | 14 | FT_STRINGZ, BASE_NONE, NULL, 0, |
755 | 14 | NULL, HFILL } |
756 | 14 | }, |
757 | 14 | }; |
758 | | |
759 | 14 | static int *ett[] = { |
760 | 14 | &ett_meta, |
761 | 14 | &ett_meta_item, |
762 | 14 | &ett_meta_cell, |
763 | 14 | &ett_meta_imsi, |
764 | 14 | &ett_meta_imei |
765 | 14 | }; |
766 | | |
767 | 14 | static ei_register_info ei[] = { |
768 | 14 | { &ei_meta_malformed, { "meta.malformed", PI_MALFORMED, PI_ERROR, "Malformed data", EXPFILL }}, |
769 | 14 | { &ei_meta_invalid_header, { "meta.invalid_header_length", PI_MALFORMED, PI_ERROR, "Invalid Header Length", EXPFILL }}, |
770 | 14 | }; |
771 | | |
772 | 14 | expert_module_t* expert_meta; |
773 | | |
774 | 14 | proto_meta = proto_register_protocol("Metadata", "META", "meta"); |
775 | 14 | register_dissector("meta", dissect_meta, proto_meta); |
776 | | |
777 | 14 | proto_register_field_array(proto_meta, hf, array_length(hf)); |
778 | 14 | proto_register_subtree_array(ett, array_length(ett)); |
779 | 14 | expert_meta = expert_register_protocol(proto_meta); |
780 | 14 | expert_register_field_array(expert_meta, ei, array_length(ei)); |
781 | | |
782 | 14 | meta_dissector_table = register_dissector_table("meta.proto", |
783 | 14 | "META protocol", proto_meta, FT_UINT16, BASE_DEC); |
784 | 14 | } |
785 | | |
786 | | void |
787 | | proto_reg_handoff_meta(void) |
788 | 14 | { |
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 | 14 | data_handle = find_dissector("data"); |
796 | 14 | alcap_handle = find_dissector_add_dependency("alcap", proto_meta); |
797 | 14 | atm_untrunc_handle = find_dissector_add_dependency("atm_untruncated", proto_meta); |
798 | 14 | nbap_handle = find_dissector_add_dependency("nbap", proto_meta); |
799 | 14 | sscf_nni_handle = find_dissector_add_dependency("sscf-nni", proto_meta); |
800 | 14 | ethwithfcs_handle = find_dissector_add_dependency("eth_withfcs", proto_meta); |
801 | 14 | ethwithoutfcs_handle = find_dissector_add_dependency("eth_withoutfcs", proto_meta); |
802 | 14 | fphint_handle = find_dissector_add_dependency("fp_hint", proto_meta); |
803 | 14 | mtp2_handle = find_dissector_add_dependency("mtp2", proto_meta); |
804 | 14 | } |
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 | | */ |