Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-log3gpp.c
blob9390a565094f87c77ce69a516ebd2ab1fe315e56
1 /* packet-log3gpp.c
2 * Routines for dissecting phone logs containing 3GPP protocol messages.
3 * Copyright 2008, Vincent Helfre
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
12 #include "config.h"
14 #include <epan/packet.h>
15 #include <epan/prefs.h>
16 #include <epan/proto_data.h>
17 #include <wiretap/wtap.h>
18 #include <wsutil/strtoi.h>
19 #include <wsutil/array.h>
21 #include "packet-mac-lte.h"
22 #include "packet-pdcp-lte.h"
23 #include "packet-rlc-lte.h"
25 #define FD1 0
26 #define REL8 1
28 void proto_register_log3gpp(void);
29 void proto_reg_handoff_log3gpp(void);
31 /* Protocol and registered fields. */
32 static int proto_log3gpp;
35 static int hf_log3gpp_timestamp;
36 static int hf_log3gpp_protocol;
37 static int hf_log3gpp_direction;
38 static int hf_log3gpp_dissector_option;
39 static int hf_log3gpp_unparsed_data;
40 static int hf_log3gpp_dissected_length;
42 /* Protocol subtree. */
43 static int ett_log3gpp;
45 /* Variables used to select a version for RRC and NAS */
46 static int lte_rrc_prot_version = REL8;
47 static int nas_eps_prot_version = REL8;
49 static const enum_val_t lte_rrc_dissector_version[] = {
50 {"FD1", "FD1", FD1},
51 {"Rel8", "Rel8 dec 2008", REL8}, /* Add new dissector version after */
52 {NULL, NULL, -1}
55 static const enum_val_t nas_eps_dissector_version[] = {
56 {"FD1", "FD1", FD1},
57 {"Rel8", "Rel8 dec 2008", REL8}, /* Add new dissector version after */
58 {NULL, NULL, -1}
61 typedef enum packet_direction_t
63 UPLINK,
64 DOWNLINK
65 } packet_direction_t;
67 static const value_string direction_vals[] = {
68 { 0, "Uplink" },
69 { 1, "Downlink" },
70 { 0, NULL },
72 /* Pseudo header functions*/
73 typedef bool (*pseudo_hdr_func_ptr_t) (char *, packet_info *pinfo, uint16_t, packet_direction_t);
75 static bool lte_mac_pseudo_hdr(char *, packet_info *pinfo, uint16_t, packet_direction_t);
76 static bool lte_rlc_pseudo_hdr(char *, packet_info *pinfo, uint16_t, packet_direction_t);
77 static bool lte_pdcp_pseudo_hdr(char *, packet_info *pinfo, uint16_t, packet_direction_t);
79 typedef struct
81 const char * protocol_name;
82 const char * ul_dissector_name;
83 const char * dl_dissector_name;
84 dissector_handle_t ul_dissector_handle;
85 dissector_handle_t dl_dissector_handle;
86 pseudo_hdr_func_ptr_t hdr_process;
87 } lookup_dissector_element_t;
89 /* Look up table for protocol name /dissector: should be in alphabetic order!!!
90 the purpose is to match a protocol name with a dissector,
91 and to store the dissector handle the first time to avoid looking it up every time.
92 This table should contain all 3GPP specified protocols */
93 static lookup_dissector_element_t dissector_lookup_table[] = {
94 {"DATA","data","data",0,0,NULL},
95 {"GAN.TCP","umatcp","umatcp",0,0,NULL},
96 {"GAN.UDP","umaudp","umaudp",0,0,NULL},
97 {"GSM.CCCH","gsm_a_ccch","gsm_a_ccch",0,0,NULL},
98 {"GSM.SACCH","gsm_a_sacch","gsm_a_sacch",0,0,NULL},
99 {"GTP","gtp","gtp",0,0,NULL},
100 {"LLC","llcgprs","llcgprs",0,0,NULL},
101 {"LTE-MAC","mac-lte","mac-lte",0,0, lte_mac_pseudo_hdr},
102 {"LTE-PDCP","pdcp-lte","pdcp-lte",0,0, lte_pdcp_pseudo_hdr},
103 {"LTE-RLC","rlc-lte","rlc-lte",0,0, lte_rlc_pseudo_hdr},
104 {"LTE-RRC.BCCH.BCH",0,0,0,0,NULL}, /* Dissector set according to preferences (depending on the release) */
105 {"LTE-RRC.BCCH.DL.SCH",0,0,0,0,NULL}, /* Dissector set according to preferences (depending on the release) */
106 {"LTE-RRC.CCCH",0,0,0,0,NULL}, /* Dissector set according to preferences (depending on the release) */
107 {"LTE-RRC.DCCH",0,0,0,0,NULL}, /* Dissector set according to preferences (depending on the release) */
108 {"LTE-RRC.PCCH",0,0,0,0,NULL}, /* Dissector set according to preferences (depending on the release) */
109 {"NAS","gsm_a_dtap","gsm_a_dtap",0,0,NULL},
110 {"NAS-EPS",0,0,0,0,NULL}, /* Dissector set according to preferences (depending on the release) */
111 {"RR","gsm_a_dtap","gsm_a_dtap",0,0,NULL},
112 {"RRC.BCCH.BCH","rrc.bcch.bch","rrc.bcch.bch",0,0,NULL},
113 {"RRC.BCCH.FACH","rrc.bcch.fach","rrc.bcch.fach",0,0,NULL},
114 {"RRC.CCCH","rrc.ul.ccch","rrc.dl.ccch",0,0,NULL},
115 {"RRC.DCCH","rrc.ul.dcch","rrc.dl.dcch",0,0,NULL},
116 {"RRC.MCCH","rrc.mcch","rrc.mcch",0,0,NULL},
117 {"RRC.MSCH","rrc.msch","rrc.msch",0,0,NULL},
118 {"RRC.PCCH","rrc.pcch","rrc.pcch",0,0,NULL},
119 {"RRC.SHCCH","rrc.ul.shcch","rrc.dl.shcch",0,0,NULL},
120 {"RRC.SI.MIB","rrc.si.mib","rrc.si.mib",0,0,NULL},
121 {"RRC.SI.SB1","rrc.sb1","rrc.sb1",0,0,NULL},
122 {"RRC.SI.SB2","rrc.sb2","rrc.sb2",0,0,NULL},
123 {"RRC.SI.SIB1","rrc.si.sib1","rrc.si.sib1",0,0,NULL},
124 {"RRC.SI.SIB10","rrc.si.sib10","rrc.si.sib10",0,0,NULL},
125 {"RRC.SI.SIB11","rrc.si.sib11","rrc.si.sib11",0,0,NULL},
126 {"RRC.SI.SIB11bis","rrc.si.sib11bis","rrc.si.sib11bis",0,0,NULL},
127 {"RRC.SI.SIB12","rrc.si.sib12","rrc.si.sib12",0,0,NULL},
128 {"RRC.SI.SIB13","rrc.si.sib13","rrc.si.sib13",0,0,NULL },
129 {"RRC.SI.SIB13-1","rrc.si.sib13-1","rrc.si.sib13-1",0,0,NULL},
130 {"RRC.SI.SIB13-2","rrc.si.sib13-2","rrc.si.sib13-2",0,0,NULL},
131 {"RRC.SI.SIB13-3","rrc.si.sib13-3","rrc.si.sib13-3",0,0,NULL },
132 {"RRC.SI.SIB13-4","rrc.si.sib13-4","rrc.si.sib13-4",0,0,NULL},
133 {"RRC.SI.SIB14","rrc.si.sib14","rrc.si.sib14",0,0,NULL},
134 {"RRC.SI.SIB15","rrc.si.sib15","rrc.si.sib15",0,0,NULL},
135 {"RRC.SI.SIB15bis","rrc.si.sib15bis","rrc.si.sib15bis",0,0,NULL},
136 {"RRC.SI.SIB15-1","rrc.si.sib15-1","rrc.si.sib15-1",0,0,NULL},
137 {"RRC.SI.SIB15-1bis","rrc.si.sib15-1bis","rrc.si.sib15-1bis",0,0,NULL },
138 {"RRC.SI.SIB15-2","rrc.si.sib15-2","rrc.si.sib15-2",0,0,NULL},
139 {"RRC.SI.SIB15-2bis","rrc.si.sib15-2bis","rrc.si.sib15-2bis",0,0,NULL},
140 {"RRC.SI.SIB15-3","rrc.si.sib15-3","rrc.si.sib15-3",0,0,NULL},
141 {"RRC.SI.SIB15-3bis","rrc.si.sib15-3bis","rrc.si.sib15-3bis",0,0,NULL},
142 {"RRC.SI.SIB15-4","rrc.si.sib15-4","rrc.si.sib15-4",0,0,NULL},
143 {"RRC.SI.SIB15-5","rrc.si.sib15-5","rrc.si.sib15-5",0,0,NULL},
144 {"RRC.SI.SIB15-6","rrc.si.sib15-6","rrc.si.sib15-6",0,0,NULL},
145 {"RRC.SI.SIB15-7","rrc.si.sib15-7","rrc.si.sib15-7",0,0,NULL},
146 {"RRC.SI.SIB15-8","rrc.si.sib15-8","rrc.si.sib15-8",0,0,NULL},
147 {"RRC.SI.SIB18","rrc.si.sib18","rrc.si.sib18",0,0,NULL},
148 {"RRC.SI.SIB17","rrc.si.sib17","rrc.si.sib17",0,0,NULL},
149 {"RRC.SI.SIB18","rrc.si.sib18","rrc.si.sib18",0,0,NULL},
150 {"RRC.SI.SIB2","rrc.si.sib2","rrc.si.sib2",0,0,NULL},
151 {"RRC.SI.SIB3","rrc.si.sib3","rrc.si.sib3",0,0,NULL},
152 {"RRC.SI.SIB4","rrc.si.sib4","rrc.si.sib4",0,0,NULL},
153 {"RRC.SI.SIB5","rrc.si.sib5","rrc.si.sib5",0,0,NULL},
154 {"RRC.SI.SIB5bis","rrc.si.sib5bis","rrc.si.sib5bis",0,0,NULL},
155 {"RRC.SI.SIB6","rrc.si.sib6","rrc.si.sib6",0,0,NULL},
156 {"RRC.SI.SIB7","rrc.si.sib7","rrc.si.sib7",0,0,NULL},
157 {"RRC.SI.SIB8","rrc.si.sib8","rrc.si.sib8",0,0,NULL},
158 {"RRC.SI.SIB9","rrc.si.sib9","rrc.si.sib9",0,0,NULL},
159 {"SNDCP","sndcp","sndcp",0,0,NULL},
160 {"SNDCPXID","sndcpxid","sndcpxid",0,0,NULL}
164 static int
165 dissector_element_compare(const void *protocol_name, const void *element)
167 return strcmp((const char *)protocol_name, ((const lookup_dissector_element_t *) element)->protocol_name);
170 static dissector_handle_t
171 look_for_dissector(char* protocol_name, packet_direction_t direction, pseudo_hdr_func_ptr_t* func_ptr _U_)
173 lookup_dissector_element_t* element_ptr;
174 dissector_handle_t dissector_handle = NULL;
176 element_ptr = (lookup_dissector_element_t*)bsearch((void*)protocol_name,
177 (void*)dissector_lookup_table,
178 array_length(dissector_lookup_table),
179 sizeof dissector_lookup_table[0],
180 dissector_element_compare);
181 if (element_ptr != NULL) {
182 if (direction == UPLINK)
184 if (element_ptr->ul_dissector_handle == 0)
186 element_ptr->ul_dissector_handle = find_dissector(element_ptr->ul_dissector_name);
188 dissector_handle = element_ptr->ul_dissector_handle;
190 else
192 if (element_ptr->dl_dissector_handle == 0)
194 element_ptr->dl_dissector_handle = find_dissector(element_ptr->dl_dissector_name);
196 dissector_handle = element_ptr->dl_dissector_handle;
201 return dissector_handle;
204 static void
205 update_dissector_name(const char* protocol_name, packet_direction_t direction, const char* dissector_name)
207 lookup_dissector_element_t* element_ptr;
209 element_ptr = (lookup_dissector_element_t*)bsearch((void*)protocol_name,
210 (void*)dissector_lookup_table,
211 array_length(dissector_lookup_table),
212 sizeof dissector_lookup_table[0],
213 dissector_element_compare);
214 if (element_ptr != NULL) {
215 if (direction == UPLINK)
217 element_ptr->ul_dissector_handle = 0;
218 element_ptr->ul_dissector_name = dissector_name;
220 else
222 element_ptr->dl_dissector_handle = 0;
223 element_ptr->dl_dissector_name = dissector_name;
229 /******************************************************************************/
230 /* pseudo header functions: used for the dissectors that needs pseudo headers */
231 /******************************************************************************/
234 /* In the optional string, MAC info should be set as follow (M = mandatory, O = optional):
235 * Radio type (M): "FDD" or "TDD"
236 * RNTI type (M): "NO_RNTI" or "P_RNTI" or "RA_RNTI" or "C_RNTI" or "SI_RNT" followed by rnti value in decimal format
237 * subframe number (M): "SFN" followed by the subframe number in decimal format
239 static bool
240 lte_mac_pseudo_hdr(char* option_str, packet_info* pinfo, uint16_t length, packet_direction_t direction)
242 struct mac_lte_info* p_mac_lte_info;
243 char* par_opt_field;
244 char option[30];
245 static int proto_mac_lte = 0;
247 /* look up for protocol handle */
248 if (proto_mac_lte == 0)
250 proto_mac_lte = proto_get_id_by_filter_name("mac-lte");
253 /* Need to copy the string in a local buffer since strtok will modify it */
254 (void) g_strlcpy(option, option_str, 30);
256 /* Only need to set info once per session. */
257 p_mac_lte_info = (struct mac_lte_info*)p_get_proto_data(wmem_file_scope(), pinfo, proto_mac_lte, 0);
258 if (p_mac_lte_info != NULL)
260 return 1;
263 /* Allocate & zero struct */
264 p_mac_lte_info = (struct mac_lte_info*) wmem_new0(pinfo->pool, mac_lte_info);
266 /* First mandatory parameter */
267 par_opt_field = strtok(option, " ");
268 if (par_opt_field == NULL)
270 return 0;
272 if (strcmp(par_opt_field, "FDD") == 0)
274 p_mac_lte_info->radioType = FDD_RADIO;
276 else if (strcmp(par_opt_field, "TDD") == 0)
278 p_mac_lte_info->radioType = TDD_RADIO;
280 else
282 return 0;
285 /* Second mandatory parameter */
286 par_opt_field = strtok(NULL, " ");
287 if (par_opt_field == NULL)
289 return 0;
291 if (strcmp(par_opt_field, "NO_RNTI") == 0)
293 p_mac_lte_info->rntiType = NO_RNTI;
295 else if (strcmp(par_opt_field, "P_RNTI") == 0)
297 p_mac_lte_info->rntiType = P_RNTI;
299 else if (strcmp(par_opt_field, "RA_RNTI") == 0)
301 p_mac_lte_info->rntiType = RA_RNTI;
303 else if (strcmp(par_opt_field, "C_RNTI") == 0)
305 p_mac_lte_info->rntiType = C_RNTI;
307 else if (strcmp(par_opt_field, "SI_RNTI") == 0)
309 p_mac_lte_info->rntiType = SI_RNTI;
311 else
313 return 0;
315 /* Get the associated rnti value */
316 par_opt_field = strtok(NULL, " ");
317 if (par_opt_field)
319 ws_strtoi16(par_opt_field, NULL, &p_mac_lte_info->rnti);
321 else
323 return 0;
326 /* First optional parameter */
327 p_mac_lte_info->subframeNumber = 0;
328 par_opt_field = strtok(NULL, " ");
329 if (par_opt_field == NULL)
331 return 0;
333 if (strcmp(par_opt_field, "SFN") == 0)
335 par_opt_field = strtok(NULL, " ");
336 if (par_opt_field != NULL)
338 ws_strtoi16(par_opt_field, NULL, &p_mac_lte_info->subframeNumber);
341 p_mac_lte_info->direction = (direction == UPLINK) ? DIRECTION_UPLINK : DIRECTION_DOWNLINK;
342 p_mac_lte_info->length = length;
344 /* Store info in packet */
345 p_add_proto_data(wmem_file_scope(), pinfo, proto_mac_lte, 0, p_mac_lte_info);
347 return 1;
350 /* In the optional string, RLC info should be set as follow (M = mandatory, O = optional):
351 * Channel type (M): "SRB" or "DRB" followed by the RB ID
352 * RLC mode (M): "TM" or "UM" or "AM" or "NA"
353 * UM Sequence nb length (O): "SN_5b" or "SN_10b"
356 static bool
357 lte_rlc_pseudo_hdr(char* option_str, packet_info* pinfo, uint16_t length, packet_direction_t direction)
359 struct rlc_lte_info* p_rlc_lte_info;
360 char* par_opt_field;
361 char option[30];
362 static int proto_rlc_lte = 0;
364 /* look up for protocol handle */
365 if (proto_rlc_lte == 0)
367 proto_rlc_lte = proto_get_id_by_filter_name("rlc-lte");
369 (void) g_strlcpy(option, option_str, 30);
371 /* Only need to set info once per session. */
372 p_rlc_lte_info = (struct rlc_lte_info*)p_get_proto_data(wmem_file_scope(), pinfo, proto_rlc_lte, 0);
373 if (p_rlc_lte_info != NULL)
375 return 1;
378 /* Allocate & zero struct */
379 p_rlc_lte_info = (struct rlc_lte_info*) wmem_new0(pinfo->pool, rlc_lte_info);
380 /* First mandatory parameter */
381 par_opt_field = strtok(option, " ");
382 if (par_opt_field == NULL)
384 return 0;
386 if (strcmp(par_opt_field, "SRB") == 0)
388 p_rlc_lte_info->channelType = CHANNEL_TYPE_SRB;
390 else if (strcmp(par_opt_field, "DRB") == 0)
392 p_rlc_lte_info->channelType = CHANNEL_TYPE_DRB;
394 else
396 return 0;
398 /* Fill in the RB ID */
399 par_opt_field = strtok(NULL, " ");
400 if (par_opt_field == NULL)
402 return 0;
404 ws_strtou16(par_opt_field, NULL, &p_rlc_lte_info->channelId);
406 /* Second mandatory parameter */
407 par_opt_field = strtok(NULL, " ");
408 if (par_opt_field == NULL)
410 return 0;
412 if (strcmp(par_opt_field, "TM") == 0)
414 p_rlc_lte_info->rlcMode = RLC_TM_MODE;
416 else if (strcmp(par_opt_field, "UM") == 0)
418 p_rlc_lte_info->rlcMode = RLC_UM_MODE;
420 else if (strcmp(par_opt_field, "AM") == 0)
422 p_rlc_lte_info->rlcMode = RLC_AM_MODE;
424 else if (strcmp(par_opt_field, "NA") == 0)
426 p_rlc_lte_info->rlcMode = RLC_PREDEF;
428 else
430 return 0;
433 /* First optional parameter */
434 par_opt_field = strtok(NULL, " ");
435 if (par_opt_field != NULL)
437 if (strcmp(par_opt_field, "SN_5b") == 0)
439 p_rlc_lte_info->sequenceNumberLength = UM_SN_LENGTH_5_BITS;
441 else if (strcmp(par_opt_field, "SN_10b") == 0)
443 p_rlc_lte_info->sequenceNumberLength = UM_SN_LENGTH_10_BITS;
446 p_rlc_lte_info->direction = (direction == UPLINK) ? DIRECTION_UPLINK : DIRECTION_DOWNLINK;
447 p_rlc_lte_info->priority = 0;
448 p_rlc_lte_info->ueid = 0;
449 p_rlc_lte_info->pduLength = length;
451 /* Store info in packet */
452 p_add_proto_data(wmem_file_scope(), pinfo, proto_rlc_lte, 0, p_rlc_lte_info);
454 return 1;
457 /* In the optional string, PDCP info should be set as follow (M = mandatory, O = optional):
458 * Plane: "SRB" or "DRB"
459 * Sequence number length: "SN_7b" or "SN_12b"
461 static bool
462 lte_pdcp_pseudo_hdr(char* option_str, packet_info* pinfo, uint16_t length _U_, packet_direction_t direction)
464 struct pdcp_lte_info* p_pdcp_lte_info;
465 char* par_opt_field;
466 char option[30];
467 static int proto_pdcp_lte = 0;
469 /* look up for protocol handle */
470 if (proto_pdcp_lte == 0)
472 proto_pdcp_lte = proto_get_id_by_filter_name("pdcp-lte");
474 (void) g_strlcpy(option, option_str, 30);
476 /* Only need to set info once per session. */
477 p_pdcp_lte_info = (struct pdcp_lte_info*)p_get_proto_data(wmem_file_scope(), pinfo, proto_pdcp_lte, 0);
478 if (p_pdcp_lte_info != NULL)
480 return 1;
483 /* Allocate & zero struct */
484 p_pdcp_lte_info = (struct pdcp_lte_info*) wmem_new0(pinfo->pool, pdcp_lte_info);
485 /* First mandatory parameter */
486 par_opt_field = strtok(option, " ");
487 if (par_opt_field == NULL)
489 return 0;
491 if (strcmp(par_opt_field, "SRB") == 0)
493 p_pdcp_lte_info->plane = SIGNALING_PLANE;
495 else if (strcmp(par_opt_field, "DRB") == 0)
497 p_pdcp_lte_info->plane = USER_PLANE;
499 else
501 return 0;
503 /* Second mandatory parameter */
504 par_opt_field = strtok(NULL, " ");
505 if (par_opt_field == NULL)
507 return 0;
509 if (strcmp(par_opt_field, "SN_7b") == 0)
511 p_pdcp_lte_info->seqnum_length = PDCP_SN_LENGTH_7_BITS;
513 else if (strcmp(par_opt_field, "SN_12b") == 0)
515 p_pdcp_lte_info->seqnum_length = PDCP_SN_LENGTH_12_BITS;
517 else
519 return 0;
521 p_pdcp_lte_info->no_header_pdu = 0;
522 p_pdcp_lte_info->rohc.rohc_compression = 0;
523 p_pdcp_lte_info->direction = (direction == UPLINK) ? DIRECTION_UPLINK : DIRECTION_DOWNLINK;
525 /* Store info in packet */
526 p_add_proto_data(wmem_file_scope(), pinfo, proto_pdcp_lte, 0, p_pdcp_lte_info);
528 return 1;
532 /*****************************************/
533 /* Main dissection function. */
534 /*****************************************/
535 static int
536 dissect_log3gpp(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data _U_)
538 proto_tree* prot3gpp_tree = NULL;
539 proto_item* ti = NULL;
540 int offset = 0;
541 int protocol_name_start;
542 int protocol_name_length;
543 int protocol_option_start;
544 int protocol_option_length;
545 int timestamp_start;
546 int timestamp_length;
547 packet_direction_t direction;
548 tvbuff_t* next_tvb;
549 dissector_handle_t protocol_handle = 0;
550 int sub_dissector_result = 0;
551 char* protocol_name;
552 char* protocol_option;
553 bool is_hex_data;
555 /* Clear Info */
556 col_clear(pinfo->cinfo, COL_INFO);
558 /* Create root (protocol) tree. */
559 ti = proto_tree_add_item(tree, proto_log3gpp, tvb, offset, -1, ENC_NA);
560 prot3gpp_tree = proto_item_add_subtree(ti, ett_log3gpp);
562 /*********************************************************************/
563 /* Note that these are the fields of the stub header as written out */
564 /* by the wiretap module */
566 /* Timestamp in file */
567 timestamp_start = offset;
568 timestamp_length = tvb_strsize(tvb, offset);
569 if (prot3gpp_tree) {
570 proto_tree_add_double_format_value(prot3gpp_tree, hf_log3gpp_timestamp, tvb,
571 offset, timestamp_length,
572 g_ascii_strtod(tvb_format_text(pinfo->pool, tvb, offset, timestamp_length), NULL),
573 "%s", tvb_format_text(pinfo->pool, tvb, offset, timestamp_length - 1));
575 offset += timestamp_length;
578 /* protocol name */
579 protocol_name_start = offset;
580 protocol_name_length = tvb_strsize(tvb, offset);
581 if (prot3gpp_tree) {
582 proto_tree_add_item(prot3gpp_tree, hf_log3gpp_protocol, tvb, offset, protocol_name_length, ENC_ASCII | ENC_NA);
584 offset += protocol_name_length;
586 /* Direction */
587 direction = (packet_direction_t)tvb_get_uint8(tvb, offset);
588 if (prot3gpp_tree) {
589 proto_tree_add_item(prot3gpp_tree, hf_log3gpp_direction, tvb, offset, 1, ENC_BIG_ENDIAN);
591 offset++;
593 /* protocol option */
594 protocol_option_start = offset;
595 protocol_option_length = tvb_strsize(tvb, offset);
596 if (prot3gpp_tree) {
597 proto_tree_add_item(prot3gpp_tree, hf_log3gpp_dissector_option, tvb, offset, protocol_option_length, ENC_ASCII | ENC_NA);
599 offset += protocol_option_length;
601 if (prot3gpp_tree)
603 /* Set selection length of prot3gpp tree */
604 proto_item_set_len(prot3gpp_tree, offset);
607 /* Add useful details to protocol tree label */
608 protocol_name = (char*)tvb_get_string_enc(pinfo->pool, tvb, protocol_name_start, protocol_name_length, ENC_UTF_8 | ENC_NA);
609 /* Set Protocol */
610 col_set_str(pinfo->cinfo, COL_PROTOCOL, protocol_name);
611 /* To know whether the data following is row byte stream or text data */
612 is_hex_data = strcmp(protocol_name, "TXT");
614 proto_item_append_text(ti, " t=%s %c prot=%s",
615 tvb_get_string_enc(pinfo->pool, tvb, timestamp_start, timestamp_length, ENC_UTF_8 | ENC_NA),
616 (direction == 0) ? 'U' : 'D',
617 protocol_name);
619 if (is_hex_data)
621 /* We might need to prepend pseudo header for the dissector */
622 pseudo_hdr_func_ptr_t func_ptr = NULL;
624 /* Look up for the optional information */
625 protocol_option = (char*)tvb_get_string_enc(pinfo->pool, tvb, protocol_option_start, protocol_option_length, ENC_UTF_8 | ENC_NA);
627 /* look up for the right dissector handle */
628 protocol_handle = look_for_dissector(protocol_name, direction, &func_ptr);
630 /***********************************************************************/
631 /* Now hand off to the dissector of intended packet encapsulation type */
633 /* Try appropriate dissector, if one has been selected */
634 if (protocol_handle != 0)
636 /* Dissect the remainder of the frame using chosen protocol handle */
637 next_tvb = tvb_new_subset_length_caplen(tvb, offset, -1, tvb_reported_length(tvb) - offset);
639 /* This part is optional, only for dissector that need pseudo header information */
640 if (func_ptr != NULL && strlen(protocol_option) != 0)
642 if (func_ptr(protocol_option, pinfo, offset, direction) == 0)
644 /* There was an error, return */
645 return tvb_reported_length(tvb);
648 sub_dissector_result = call_dissector(protocol_handle, next_tvb, pinfo, tree);
652 if (protocol_handle == 0 || sub_dissector_result == 0)
654 /* Could get here because:
655 - desired protocol is unavailable (probably disabled), OR
656 - protocol rejected our data
657 Show remaining bytes as unparsed data */
658 proto_tree_add_item(prot3gpp_tree, hf_log3gpp_unparsed_data, tvb, offset, -1, ENC_NA);
660 if (!is_hex_data)
662 col_add_str(pinfo->cinfo, COL_INFO,
663 tvb_get_string_enc(pinfo->pool, tvb, offset, tvb_reported_length(tvb) - offset, ENC_UTF_8 | ENC_NA));
665 else
667 col_add_fstr(pinfo->cinfo, COL_INFO,
668 "Not dissected ( t=%s %c prot=%s)",
669 tvb_get_string_enc(pinfo->pool, tvb, timestamp_start, timestamp_length, ENC_UTF_8 | ENC_NA),
670 (direction == 0) ? 'U' : 'D',
671 tvb_get_string_enc(pinfo->pool, tvb, protocol_name_start, protocol_name_length, ENC_UTF_8 | ENC_NA));
674 else
676 /* Show number of dissected bytes */
677 proto_item* ti_local = proto_tree_add_uint(prot3gpp_tree,
678 hf_log3gpp_dissected_length,
679 tvb, 0, 0, tvb_reported_length(tvb) - offset);
680 proto_item_set_generated(ti_local);
682 return tvb_reported_length(tvb);
685 /******************************************************************************/
686 /* Associate this protocol with the log3gpp file encapsulation type. */
687 /******************************************************************************/
688 void proto_reg_handoff_log3gpp(void)
690 static bool init = false;
692 if (init == false)
694 dissector_handle_t log3gpp_handle;
696 log3gpp_handle = find_dissector("prot3gpp");
697 dissector_add_uint("wtap_encap", WTAP_ENCAP_LOG_3GPP, log3gpp_handle);
698 init = true;
700 if (lte_rrc_prot_version == REL8)
702 update_dissector_name("LTE-RRC.BCCH.BCH", UPLINK, "lte-rrc.bcch.bch");
703 update_dissector_name("LTE-RRC.BCCH.BCH", DOWNLINK, "lte-rrc.bcch.bch");
704 update_dissector_name("LTE-RRC.BCCH.DL.SCH", UPLINK, "lte-rrc.bcch.dl.sch");
705 update_dissector_name("LTE-RRC.BCCH.DL.SCH", DOWNLINK, "lte-rrc.bcch.dl.sch");
706 update_dissector_name("LTE-RRC.CCCH", UPLINK, "lte-rrc.ul.ccch");
707 update_dissector_name("LTE-RRC.CCCH", DOWNLINK, "lte-rrc.dl.ccch");
708 update_dissector_name("LTE-RRC.DCCH", UPLINK, "lte-rrc.ul.dcch");
709 update_dissector_name("LTE-RRC.DCCH", DOWNLINK, "lte-rrc.dl.dcch");
710 update_dissector_name("LTE-RRC.PCCH", UPLINK, "lte-rrc.pcch");
711 update_dissector_name("LTE-RRC.PCCH", DOWNLINK, "lte-rrc.pcch");
713 else if (lte_rrc_prot_version == FD1)
715 update_dissector_name("LTE-RRC.BCCH.BCH", UPLINK, "lte-rrc-fd1.bcch.bch");
716 update_dissector_name("LTE-RRC.BCCH.BCH", DOWNLINK, "lte-rrc-fd1.bcch.bch");
717 update_dissector_name("LTE-RRC.BCCH.DL.SCH", UPLINK, "lte-rrc-fd1.bcch.dl.sch");
718 update_dissector_name("LTE-RRC.BCCH.DL.SCH", DOWNLINK, "lte-rrc-fd1.bcch.dl.sch");
719 update_dissector_name("LTE-RRC.CCCH", UPLINK, "lte-rrc-fd1.ul.ccch");
720 update_dissector_name("LTE-RRC.CCCH", DOWNLINK, "lte-rrc-fd1.dl.ccch");
721 update_dissector_name("LTE-RRC.DCCH", UPLINK, "lte-rrc-fd1.ul.dcch");
722 update_dissector_name("LTE-RRC.DCCH", DOWNLINK, "lte-rrc-fd1.dl.dcch");
723 update_dissector_name("LTE-RRC.PCCH", UPLINK, "lte-rrc-fd1.pcch");
724 update_dissector_name("LTE-RRC.PCCH", DOWNLINK, "lte-rrc-fd1.pcch");
726 if (nas_eps_prot_version == REL8)
728 update_dissector_name("NAS-EPS", UPLINK, "nas-eps");
729 update_dissector_name("NAS-EPS", DOWNLINK, "nas-eps");
731 else if (nas_eps_prot_version == FD1)
733 update_dissector_name("NAS-EPS", UPLINK, "nas-eps-fd1");
734 update_dissector_name("NAS-EPS", DOWNLINK, "nas-eps-fd1");
738 /****************************************/
739 /* Register the protocol */
740 /****************************************/
741 void proto_register_log3gpp(void)
743 module_t *log3gpp_module;
744 static hf_register_info hf[] =
746 { &hf_log3gpp_timestamp,
747 { "Timestamp",
748 "log3gpp.timestamp", FT_DOUBLE, BASE_NONE, NULL, 0x0,
749 "File timestamp", HFILL
752 { &hf_log3gpp_protocol,
753 { "3GPP protocol",
754 "log3gpp.protocol", FT_STRING, BASE_NONE, NULL, 0x0,
755 "Original 3GPP protocol name", HFILL
758 { &hf_log3gpp_dissector_option,
759 { "option",
760 "log3gpp.option", FT_STRING, BASE_NONE, NULL, 0x0,
761 "Protocol option", HFILL
764 { &hf_log3gpp_direction,
765 { "Direction",
766 "log3gpp.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
767 "Frame direction (Uplink or Downlink)", HFILL
770 { &hf_log3gpp_unparsed_data,
771 { "Unparsed protocol data",
772 "log3gpp.unparsed_data", FT_BYTES, BASE_NONE, NULL, 0x0,
773 "Unparsed 3GPP protocol data", HFILL
776 { &hf_log3gpp_dissected_length,
777 { "Dissected length",
778 "log3gpp.dissected-length", FT_UINT16, BASE_DEC, NULL, 0x0,
779 "Number of bytes dissected by subdissector(s)", HFILL
784 static int *ett[] =
786 &ett_log3gpp
789 /* Register protocol. */
790 proto_log3gpp = proto_register_protocol("3GPP log packet",
791 "LOG3GPP",
792 "log3gpp");
793 proto_register_field_array(proto_log3gpp, hf, array_length(hf));
794 proto_register_subtree_array(ett, array_length(ett));
796 log3gpp_module = prefs_register_protocol(proto_log3gpp, proto_reg_handoff_log3gpp);
797 prefs_register_enum_preference(log3gpp_module,
798 "rrc_release_version",
799 "Select the release version of LTE RRC protocol",
800 "There might be plugins corresponding to different version of the specification "
801 "If they are present they should be listed here.",
802 &lte_rrc_prot_version,
803 lte_rrc_dissector_version,
804 false);
806 prefs_register_enum_preference(log3gpp_module,
807 "nas_eps_release_version",
808 "Select the release version of NAS EPS protocol",
809 "There might be plugins corresponding to different version of the specification "
810 "If they are present they should be listed here.",
811 &nas_eps_prot_version,
812 nas_eps_dissector_version,
813 false);
815 /* Allow dissector to find be found by name. */
816 register_dissector("prot3gpp", dissect_log3gpp, proto_log3gpp);
820 * Editor modelines - https://www.wireshark.org/tools/modelines.html
822 * Local variables:
823 * c-basic-offset: 4
824 * tab-width: 8
825 * indent-tabs-mode: nil
826 * End:
828 * vi: set shiftwidth=4 tabstop=8 expandtab:
829 * :indentSize=4:tabSize=8:noTabs=true: