Coverage Report

Created: 2026-11-12 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-gsm_gsup.c
Line
Count
Source
1
/* packet-gsm_gsup.c
2
 * Dissector for Osmocom Generic Subscriber Update Protocol (GSUP)
3
 *
4
 * (C) 2017-2018 by Harald Welte <laforge@gnumonks.org>
5
 * Contributions by sysmocom - s.f.m.c. GmbH
6
 *
7
 * Wireshark - Network traffic analyzer
8
 * By Gerald Combs <gerald@wireshark.org>
9
 * Copyright 1998 Gerald Combs
10
 *
11
 * SPDX-License-Identifier: GPL-2.0-or-later
12
 */
13
14
#include "config.h"
15
16
#include <epan/packet.h>
17
#include <epan/expert.h>
18
#include <epan/conversation.h>
19
#include <epan/asn1.h>
20
#include <epan/strutil.h>
21
22
#include "packet-gsm_a_common.h"
23
#include "packet-gsm_map.h"
24
#include "packet-e164.h"
25
#include "packet-e212.h"
26
#include "packet-dns.h"
27
#include "packet-ber.h"
28
#include "asn1.h"
29
30
/* GSUP is a non-standard, Osmocom-specific protocol used between cellular
31
 * network core elements and the HLR.  It is a much simplified replacement
32
 * for the GSM MAP (Mobile Application Part), which requires a full stack
33
 * of SIGTRAN transport, SCCP as well as TCP.
34
 *
35
 * More information about GSUP can be found in the OsmoHLR user manual
36
 * found at http://ftp.osmocom.org/docs/latest/osmohlr-usermanual.pdf
37
 */
38
39
/***********************************************************************
40
 * GSUP Protocol Definitions, see libosmocore/include/gsm/gsup.h
41
 ***********************************************************************/
42
43
#define OSMO_GSUP_PORT 4222
44
16
#define IPAC_PROTO_EXT_GSUP 0x05
45
46
/*! Maximum number of PDP inside \ref osmo_gsup_message */
47
#define OSMO_GSUP_MAX_NUM_PDP_INFO    10 /* GSM 09.02 limits this to 50 */
48
/*! Maximum number of auth info inside \ref osmo_gsup_message */
49
#define OSMO_GSUP_MAX_NUM_AUTH_INFO   5
50
/*! Maximum number of octets encoding MSISDN in BCD format */
51
#define OSMO_GSUP_MAX_MSISDN_LEN    9
52
53
/*! Information Element Identifiers for GSUP IEs */
54
enum osmo_gsup_iei {
55
  OSMO_GSUP_IMSI_IE     = 0x01,
56
  OSMO_GSUP_CAUSE_IE      = 0x02,
57
  OSMO_GSUP_AUTH_TUPLE_IE     = 0x03,
58
  OSMO_GSUP_PDP_INFO_COMPL_IE   = 0x04,
59
  OSMO_GSUP_PDP_INFO_IE     = 0x05,
60
  OSMO_GSUP_CANCEL_TYPE_IE    = 0x06,
61
  OSMO_GSUP_FREEZE_PTMSI_IE   = 0x07,
62
  OSMO_GSUP_MSISDN_IE     = 0x08,
63
  OSMO_GSUP_HLR_NUMBER_IE     = 0x09,
64
  OSMO_GSUP_MESSAGE_CLASS_IE    = 0x0a,
65
  OSMO_GSUP_PDP_CONTEXT_ID_IE   = 0x10,
66
  OSMO_GSUP_PDP_ADDRESS_IE      = 0x11,
67
  OSMO_GSUP_ACCESS_POINT_NAME_IE    = 0x12,
68
  OSMO_GSUP_PDP_QOS_IE      = 0x13,
69
  OSMO_GSUP_CHARG_CHAR_IE     = 0x14,
70
  OSMO_GSUP_PCO_IE      = 0x15,
71
  OSMO_GSUP_RAND_IE     = 0x20,
72
  OSMO_GSUP_SRES_IE     = 0x21,
73
  OSMO_GSUP_KC_IE       = 0x22,
74
  /* 3G support */
75
  OSMO_GSUP_IK_IE       = 0x23,
76
  OSMO_GSUP_CK_IE       = 0x24,
77
  OSMO_GSUP_AUTN_IE     = 0x25,
78
  OSMO_GSUP_AUTS_IE     = 0x26,
79
  OSMO_GSUP_RES_IE      = 0x27,
80
  OSMO_GSUP_CN_DOMAIN_IE      = 0x28,
81
  OSMO_GSUP_SUPPORTED_RAT_TYPES_IE  = 0x29,
82
  OSMO_GSUP_CURRENT_RAT_TYPE_IE   = 0x2a,
83
  OSMO_GSUP_SESSION_ID_IE     = 0x30,
84
  OSMO_GSUP_SESSION_STATE_IE    = 0x31,
85
  OSMO_GSUP_SS_INFO_IE      = 0x35,
86
  /* SM Service (see 3GPP TS 29.002, section 7.6.8) */
87
  OSMO_GSUP_SM_RP_MR_IE     = 0x40,
88
  OSMO_GSUP_SM_RP_DA_IE     = 0x41,
89
  OSMO_GSUP_SM_RP_OA_IE     = 0x42,
90
  OSMO_GSUP_SM_RP_UI_IE     = 0x43,
91
  OSMO_GSUP_SM_RP_CAUSE_IE    = 0x44,
92
  OSMO_GSUP_SM_RP_MMS_IE      = 0x45,
93
  OSMO_GSUP_SM_ALERT_RSN_IE   = 0x46,
94
95
  OSMO_GSUP_IMEI_IE     = 0x50,
96
  OSMO_GSUP_IMEI_RESULT_IE    = 0x51,
97
  OSMO_GSUP_NUM_VECTORS_REQ_IE    = 0x52,
98
99
  /* Inter-MSC handover related */
100
  OSMO_GSUP_SOURCE_NAME_IE    = 0x60,
101
  OSMO_GSUP_DESTINATION_NAME_IE   = 0x61,
102
  OSMO_GSUP_AN_APDU_IE      = 0x62,
103
  OSMO_GSUP_CAUSE_RR_IE     = 0x63,
104
  OSMO_GSUP_CAUSE_BSSAP_IE    = 0x64,
105
  OSMO_GSUP_CAUSE_SM_IE     = 0x65,
106
};
107
108
/*! GSUP message type */
109
enum osmo_gsup_message_type {
110
  OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST  = 0x04,
111
  OSMO_GSUP_MSGT_UPDATE_LOCATION_ERROR  = 0x05,
112
  OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT = 0x06,
113
114
  OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST = 0x08,
115
  OSMO_GSUP_MSGT_SEND_AUTH_INFO_ERROR = 0x09,
116
  OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT  = 0x0a,
117
118
  OSMO_GSUP_MSGT_AUTH_FAIL_REPORT   = 0x0b,
119
120
  OSMO_GSUP_MSGT_PURGE_MS_REQUEST   = 0x0c,
121
  OSMO_GSUP_MSGT_PURGE_MS_ERROR   = 0x0d,
122
  OSMO_GSUP_MSGT_PURGE_MS_RESULT    = 0x0e,
123
124
  OSMO_GSUP_MSGT_INSERT_DATA_REQUEST  = 0x10,
125
  OSMO_GSUP_MSGT_INSERT_DATA_ERROR  = 0x11,
126
  OSMO_GSUP_MSGT_INSERT_DATA_RESULT = 0x12,
127
128
  OSMO_GSUP_MSGT_DELETE_DATA_REQUEST  = 0x14,
129
  OSMO_GSUP_MSGT_DELETE_DATA_ERROR  = 0x15,
130
  OSMO_GSUP_MSGT_DELETE_DATA_RESULT = 0x16,
131
132
  OSMO_GSUP_MSGT_LOCATION_CANCEL_REQUEST  = 0x1c,
133
  OSMO_GSUP_MSGT_LOCATION_CANCEL_ERROR  = 0x1d,
134
  OSMO_GSUP_MSGT_LOCATION_CANCEL_RESULT = 0x1e,
135
136
  OSMO_GSUP_MSGT_PROC_SS_REQUEST    = 0x20,
137
  OSMO_GSUP_MSGT_PROC_SS_ERROR    = 0x21,
138
  OSMO_GSUP_MSGT_PROC_SS_RESULT   = 0x22,
139
140
  OSMO_GSUP_MSGT_MO_FORWARD_SM_REQUEST  = 0x24,
141
  OSMO_GSUP_MSGT_MO_FORWARD_SM_ERROR  = 0x25,
142
  OSMO_GSUP_MSGT_MO_FORWARD_SM_RESULT = 0x26,
143
144
  OSMO_GSUP_MSGT_MT_FORWARD_SM_REQUEST  = 0x28,
145
  OSMO_GSUP_MSGT_MT_FORWARD_SM_ERROR  = 0x29,
146
  OSMO_GSUP_MSGT_MT_FORWARD_SM_RESULT = 0x2a,
147
148
  OSMO_GSUP_MSGT_READY_FOR_SM_REQUEST = 0x2c,
149
  OSMO_GSUP_MSGT_READY_FOR_SM_ERROR = 0x2d,
150
  OSMO_GSUP_MSGT_READY_FOR_SM_RESULT  = 0x2e,
151
152
  OSMO_GSUP_MSGT_CHECK_IMEI_REQUEST = 0x30,
153
  OSMO_GSUP_MSGT_CHECK_IMEI_ERROR   = 0x31,
154
  OSMO_GSUP_MSGT_CHECK_IMEI_RESULT  = 0x32,
155
156
  OSMO_GSUP_MSGT_E_PREPARE_HANDOVER_REQUEST   = 0x34,
157
  OSMO_GSUP_MSGT_E_PREPARE_HANDOVER_ERROR     = 0x35,
158
  OSMO_GSUP_MSGT_E_PREPARE_HANDOVER_RESULT    = 0x36,
159
160
  OSMO_GSUP_MSGT_E_PREPARE_SUBSEQUENT_HANDOVER_REQUEST  = 0x38,
161
  OSMO_GSUP_MSGT_E_PREPARE_SUBSEQUENT_HANDOVER_ERROR  = 0x39,
162
  OSMO_GSUP_MSGT_E_PREPARE_SUBSEQUENT_HANDOVER_RESULT = 0x3a,
163
164
  OSMO_GSUP_MSGT_E_SEND_END_SIGNAL_REQUEST    = 0x3c,
165
  OSMO_GSUP_MSGT_E_SEND_END_SIGNAL_ERROR      = 0x3d,
166
  OSMO_GSUP_MSGT_E_SEND_END_SIGNAL_RESULT     = 0x3e,
167
168
  OSMO_GSUP_MSGT_E_PROCESS_ACCESS_SIGNALLING_REQUEST  = 0x40,
169
  OSMO_GSUP_MSGT_E_FORWARD_ACCESS_SIGNALLING_REQUEST  = 0x44,
170
171
  OSMO_GSUP_MSGT_E_CLOSE          = 0x47,
172
  OSMO_GSUP_MSGT_E_ABORT          = 0x4b,
173
174
  OSMO_GSUP_MSGT_E_ROUTING_ERROR        = 0x4e,
175
176
  OSMO_GSUP_MSGT_EPDG_TUNNEL_REQUEST      = 0x50,
177
  OSMO_GSUP_MSGT_EPDG_TUNNEL_ERROR      = 0x51,
178
  OSMO_GSUP_MSGT_EPDG_TUNNEL_RESULT     = 0x52,
179
};
180
181
#define OSMO_GSUP_IS_MSGT_REQUEST(msgt) (((msgt) & 0b00000011) == 0b00)
182
#define OSMO_GSUP_IS_MSGT_ERROR(msgt)   (((msgt) & 0b00000011) == 0b01)
183
#define OSMO_GSUP_TO_MSGT_ERROR(msgt)   (((msgt) & 0b11111100) | 0b01)
184
185
enum osmo_gsup_rat_type {
186
  OSMO_GSUP_RAT_UNKNOWN     = 0,
187
  OSMO_GSUP_RAT_GERAN_A     = 1,
188
  OSMO_GSUP_RAT_UTRAN_IU      = 2,
189
  OSMO_GSUP_RAT_EUTRAN_SGS    = 3,
190
};
191
192
enum osmo_gsup_cancel_type {
193
  OSMO_GSUP_CANCEL_TYPE_UPDATE    = 0,
194
  OSMO_GSUP_CANCEL_TYPE_WITHDRAW    = 1,
195
};
196
197
enum osmo_gsup_cn_domain {
198
  OSMO_GSUP_CN_DOMAIN_PS      = 1,
199
  OSMO_GSUP_CN_DOMAIN_CS      = 2,
200
};
201
202
enum osmo_gsup_imei_result {
203
  OSMO_GSUP_IMEI_RESULT_ACK   = 0,
204
  OSMO_GSUP_IMEI_RESULT_NACK    = 1,
205
};
206
207
enum osmo_gsup_session_state {
208
  OSMO_GSUP_SESSION_STATE_NONE    = 0x00,
209
  OSMO_GSUP_SESSION_STATE_BEGIN   = 0x01,
210
  OSMO_GSUP_SESSION_STATE_CONTINUE  = 0x02,
211
  OSMO_GSUP_SESSION_STATE_END   = 0x03,
212
};
213
214
/* Identity types for SM-RP-{OA|DA} */
215
enum osmo_gsup_sms_sm_rp_oda_type {
216
  OSMO_GSUP_SMS_SM_RP_ODA_NONE    = 0x00,
217
  OSMO_GSUP_SMS_SM_RP_ODA_IMSI    = 0x01,
218
  OSMO_GSUP_SMS_SM_RP_ODA_MSISDN    = 0x02,
219
  OSMO_GSUP_SMS_SM_RP_ODA_SMSC_ADDR = 0x03,
220
  /* Special value for noSM-RP-DA and noSM-RP-OA */
221
  OSMO_GSUP_SMS_SM_RP_ODA_NULL    = 0xff,
222
};
223
224
/* SM Alert Reason values */
225
enum osmo_gsup_sms_sm_alert_rsn_t {
226
  OSMO_GSUP_SMS_SM_ALERT_RSN_NONE   = 0x00,
227
  OSMO_GSUP_SMS_SM_ALERT_RSN_MS_PRESENT = 0x01,
228
  OSMO_GSUP_SMS_SM_ALERT_RSN_MEM_AVAIL  = 0x02,
229
};
230
231
enum osmo_gsup_access_network_protocol {
232
  OSMO_GSUP_ACCESS_NETWORK_PROTOCOL_TS3G_48006 = 1,
233
  OSMO_GSUP_ACCESS_NETWORK_PROTOCOL_TS3G_25413 = 2,
234
};
235
236
enum osmo_gsup_message_class {
237
  OSMO_GSUP_MESSAGE_CLASS_UNSET = 0,
238
  OSMO_GSUP_MESSAGE_CLASS_SUBSCRIBER_MANAGEMENT = 1,
239
  OSMO_GSUP_MESSAGE_CLASS_SMS = 2,
240
  OSMO_GSUP_MESSAGE_CLASS_USSD = 3,
241
  OSMO_GSUP_MESSAGE_CLASS_INTER_MSC = 4,
242
};
243
244
/* like TS 29.002 access network protocol ID */
245
enum osmo_gsup_an_type {
246
  OSMO_GSUP_AN_TYPE_BSSAP = 1,
247
  OSMO_GSUP_AN_TYPE_RANAP = 2,
248
};
249
250
/***********************************************************************
251
 * Wireshark Dissector Implementation
252
 ***********************************************************************/
253
254
void proto_register_gsup(void);
255
void proto_reg_handoff_gsup(void);
256
257
static int proto_gsup;
258
259
/* show GSUP source/destination names as text (true) or only binary (false) */
260
static bool show_name_as_text = true;
261
262
static int hf_gsup_msg_type;
263
static int hf_gsup_iei;
264
static int hf_gsup_ie_len;
265
static int hf_gsup_ie_payload;
266
static int hf_gsup_cause;
267
static int hf_gsup_pdp_info_compl;
268
static int hf_gsup_cancel_type;
269
static int hf_gsup_freeze_ptmsi;
270
static int hf_gsup_pdp_context_id;
271
static int hf_gsup_charg_char;
272
static int hf_gsup_apn;
273
static int hf_gsup_cn_domain;
274
static int hf_gsup_rand;
275
static int hf_gsup_sres;
276
static int hf_gsup_kc;
277
static int hf_gsup_ik;
278
static int hf_gsup_ck;
279
static int hf_gsup_autn;
280
static int hf_gsup_auts;
281
static int hf_gsup_res;
282
static int hf_gsup_session_id;
283
static int hf_gsup_session_state;
284
static int hf_gsup_sm_rp_mr;
285
static int hf_gsup_sm_rp_da_id_type;
286
static int hf_gsup_sm_rp_oa_id_type;
287
static int hf_gsup_sm_rp_cause;
288
static int hf_gsup_sm_rp_mms;
289
static int hf_gsup_sm_alert_rsn;
290
static int hf_gsup_imei_result;
291
static int hf_gsup_num_vectors_req;
292
static int hf_gsup_msg_class;
293
static int hf_gsup_an_type;
294
static int hf_gsup_source_name;
295
static int hf_gsup_source_name_text;
296
static int hf_gsup_destination_name;
297
static int hf_gsup_destination_name_text;
298
static int hf_gsup_supported_rat_type;
299
static int hf_gsup_current_rat_type;
300
static int hf_gsup_pdp_addr_type_org;
301
static int hf_gsup_spare_bits;
302
static int hf_gsup_pdp_addr_type_nr;
303
static int hf_gsup_pdp_addr_v4;
304
static int hf_gsup_pdp_addr_v6;
305
306
static int ett_gsup;
307
static int ett_gsup_ie;
308
309
static expert_field ei_sm_rp_da_invalid;
310
static expert_field ei_sm_rp_oa_invalid;
311
static expert_field ei_gsup_ie_len_invalid;
312
313
static dissector_handle_t gsm_map_handle;
314
static dissector_handle_t gsup_handle;
315
static dissector_handle_t gsm_sms_handle;
316
static dissector_handle_t bssap_imei_handle;
317
static dissector_handle_t bssap_handle;
318
static dissector_handle_t ranap_handle;
319
320
static const value_string gsup_iei_types[] = {
321
  { OSMO_GSUP_IMSI_IE,    "IMSI" },
322
  { OSMO_GSUP_CAUSE_IE,   "Cause" },
323
  { OSMO_GSUP_AUTH_TUPLE_IE,  "Authentication Tuple" },
324
  { OSMO_GSUP_PDP_INFO_COMPL_IE,  "PDP Information Complete" },
325
  { OSMO_GSUP_PDP_INFO_IE,  "PDP Information" },
326
  { OSMO_GSUP_CANCEL_TYPE_IE, "Cancel Type" },
327
  { OSMO_GSUP_FREEZE_PTMSI_IE,  "Freeze P-TMSI" },
328
  { OSMO_GSUP_MSISDN_IE,    "MSISDN" },
329
  { OSMO_GSUP_HLR_NUMBER_IE,  "HLR Number" },
330
  { OSMO_GSUP_PDP_CONTEXT_ID_IE,  "PDP Context ID" },
331
  { OSMO_GSUP_PDP_ADDRESS_IE, "PDP Address" },
332
  { OSMO_GSUP_ACCESS_POINT_NAME_IE, "Access Point Name (APN)" },
333
  { OSMO_GSUP_PDP_QOS_IE,   "PDP Quality of Service (QoS)" },
334
  { OSMO_GSUP_CHARG_CHAR_IE,  "Charging Character" },
335
  { OSMO_GSUP_PCO_IE,   "Protocol Configuration Options" },
336
  { OSMO_GSUP_RAND_IE,    "RAND" },
337
  { OSMO_GSUP_SRES_IE,    "SRES" },
338
  { OSMO_GSUP_KC_IE,    "Kc" },
339
  { OSMO_GSUP_IK_IE,    "IK" },
340
  { OSMO_GSUP_CK_IE,    "CK" },
341
  { OSMO_GSUP_AUTN_IE,    "AUTN" },
342
  { OSMO_GSUP_AUTS_IE,    "AUTS" },
343
  { OSMO_GSUP_RES_IE,   "RES" },
344
  { OSMO_GSUP_CN_DOMAIN_IE, "CN Domain" },
345
  { OSMO_GSUP_SUPPORTED_RAT_TYPES_IE, "Supported RAT Types" },
346
  { OSMO_GSUP_CURRENT_RAT_TYPE_IE, "Current RAT Type" },
347
  { OSMO_GSUP_SESSION_ID_IE,  "Session Id" },
348
  { OSMO_GSUP_SESSION_STATE_IE, "Session State" },
349
  { OSMO_GSUP_SS_INFO_IE,   "Supplementary Service Info"},
350
  { OSMO_GSUP_SM_RP_MR_IE,  "SM-RP-MR (Message Reference)" },
351
  { OSMO_GSUP_SM_RP_DA_IE,  "SM-RP-DA (Destination Address)" },
352
  { OSMO_GSUP_SM_RP_OA_IE,  "SM-RP-OA (Originating Address)" },
353
  { OSMO_GSUP_SM_RP_UI_IE,  "SM-RP-UI (SMS TPDU)" },
354
  { OSMO_GSUP_SM_RP_CAUSE_IE, "SM-RP-Cause" },
355
  { OSMO_GSUP_SM_RP_MMS_IE, "SM-RP-MMS (More Messages to Send)" },
356
  { OSMO_GSUP_SM_ALERT_RSN_IE,  "SM Alert Reason" },
357
  { OSMO_GSUP_IMEI_IE,    "IMEI" },
358
  { OSMO_GSUP_IMEI_RESULT_IE, "IMEI Check Result" },
359
  { OSMO_GSUP_NUM_VECTORS_REQ_IE, "Number of Vectors Requested" },
360
  { OSMO_GSUP_MESSAGE_CLASS_IE, "Message Class" },
361
  { OSMO_GSUP_SOURCE_NAME_IE, "Source Name"},
362
  { OSMO_GSUP_DESTINATION_NAME_IE,"Destination Name"},
363
  { OSMO_GSUP_AN_APDU_IE,   "AN-APDU"},
364
  { OSMO_GSUP_CAUSE_RR_IE,  "RR-Cause"},
365
  { OSMO_GSUP_CAUSE_BSSAP_IE, "BSSAP-Cause"},
366
  { OSMO_GSUP_CAUSE_SM_IE,  "Session Management Cause"},
367
  { 0, NULL }
368
};
369
370
static const value_string gsup_msg_types[] = {
371
  { OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST,   "UpdateLocation Request" },
372
  { OSMO_GSUP_MSGT_UPDATE_LOCATION_ERROR,   "UpdateLocation Error" },
373
  { OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT,  "UpdateLocation Result" },
374
  { OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST,  "SendAuthInfo Request" },
375
  { OSMO_GSUP_MSGT_SEND_AUTH_INFO_ERROR,    "SendAuthInfo Error" },
376
  { OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT,   "SendAuthInfo Result" },
377
  { OSMO_GSUP_MSGT_AUTH_FAIL_REPORT,    "AuthFail Report" },
378
  { OSMO_GSUP_MSGT_PURGE_MS_REQUEST,    "PurgeMS Request" },
379
  { OSMO_GSUP_MSGT_PURGE_MS_ERROR,    "PurgeMS Error" },
380
  { OSMO_GSUP_MSGT_PURGE_MS_RESULT,   "PurgeMS Result" },
381
  { OSMO_GSUP_MSGT_INSERT_DATA_REQUEST,   "InsertSubscriberData Request" },
382
  { OSMO_GSUP_MSGT_INSERT_DATA_ERROR,   "InsertSubscriberData Error" },
383
  { OSMO_GSUP_MSGT_INSERT_DATA_RESULT,    "InsertSubscriberData Result" },
384
  { OSMO_GSUP_MSGT_DELETE_DATA_REQUEST,   "DeleteSubscriberData Request" },
385
  { OSMO_GSUP_MSGT_DELETE_DATA_ERROR,   "DeleteSubscriberData Error" },
386
  { OSMO_GSUP_MSGT_DELETE_DATA_RESULT,    "DeleteSubscriberData Result" },
387
  { OSMO_GSUP_MSGT_LOCATION_CANCEL_REQUEST, "LocationCancel Request" },
388
  { OSMO_GSUP_MSGT_LOCATION_CANCEL_ERROR,   "LocationCancel Error" },
389
  { OSMO_GSUP_MSGT_LOCATION_CANCEL_RESULT,  "LocationCancel Result" },
390
  { OSMO_GSUP_MSGT_PROC_SS_REQUEST,   "Supplementary Service Request" },
391
  { OSMO_GSUP_MSGT_PROC_SS_ERROR,     "Supplementary Service Error" },
392
  { OSMO_GSUP_MSGT_PROC_SS_RESULT,    "Supplementary Service Result" },
393
  { OSMO_GSUP_MSGT_MO_FORWARD_SM_REQUEST,   "MO-forwardSM Request" },
394
  { OSMO_GSUP_MSGT_MO_FORWARD_SM_ERROR,   "MO-forwardSM Error" },
395
  { OSMO_GSUP_MSGT_MO_FORWARD_SM_RESULT,    "MO-forwardSM Result" },
396
  { OSMO_GSUP_MSGT_MT_FORWARD_SM_REQUEST,   "MT-forwardSM Request" },
397
  { OSMO_GSUP_MSGT_MT_FORWARD_SM_ERROR,   "MT-forwardSM Error" },
398
  { OSMO_GSUP_MSGT_MT_FORWARD_SM_RESULT,    "MT-forwardSM Result" },
399
  { OSMO_GSUP_MSGT_READY_FOR_SM_REQUEST,    "Ready for SM Request"},
400
  { OSMO_GSUP_MSGT_READY_FOR_SM_ERROR,    "Ready for SM Error"},
401
  { OSMO_GSUP_MSGT_READY_FOR_SM_RESULT,   "Ready for SM Result"},
402
  { OSMO_GSUP_MSGT_CHECK_IMEI_REQUEST,    "Check IMEI Request"},
403
  { OSMO_GSUP_MSGT_CHECK_IMEI_ERROR,    "Check IMEI Error"},
404
  { OSMO_GSUP_MSGT_CHECK_IMEI_RESULT,   "Check IMEI Result"},
405
  { OSMO_GSUP_MSGT_E_PREPARE_HANDOVER_REQUEST,  "E Prepare Handover Request"},
406
  { OSMO_GSUP_MSGT_E_PREPARE_HANDOVER_ERROR,  "E Prepare Handover Error"},
407
  { OSMO_GSUP_MSGT_E_PREPARE_HANDOVER_RESULT, "E Prepare Handover Result"},
408
  { OSMO_GSUP_MSGT_E_PREPARE_SUBSEQUENT_HANDOVER_REQUEST, "E Prepare Subsequent Handover Request"},
409
  { OSMO_GSUP_MSGT_E_PREPARE_SUBSEQUENT_HANDOVER_ERROR, "E Prepare Subsequent Handover Error"},
410
  { OSMO_GSUP_MSGT_E_PREPARE_SUBSEQUENT_HANDOVER_RESULT,  "E Prepare Subsequent Handover Result"},
411
  { OSMO_GSUP_MSGT_E_SEND_END_SIGNAL_REQUEST, "E Send End Signal Request"},
412
  { OSMO_GSUP_MSGT_E_SEND_END_SIGNAL_ERROR, "E Send End Signal Error"},
413
  { OSMO_GSUP_MSGT_E_SEND_END_SIGNAL_RESULT,  "E Send End Signal Result"},
414
  { OSMO_GSUP_MSGT_E_PROCESS_ACCESS_SIGNALLING_REQUEST, "E Process Access Signalling Request"},
415
  { OSMO_GSUP_MSGT_E_FORWARD_ACCESS_SIGNALLING_REQUEST, "E Forward Access Signalling Request"},
416
  { OSMO_GSUP_MSGT_E_CLOSE,     "E Close"},
417
  { OSMO_GSUP_MSGT_E_ABORT,     "E Abort"},
418
  { OSMO_GSUP_MSGT_E_ROUTING_ERROR,   "E Routing Error"},
419
  { OSMO_GSUP_MSGT_EPDG_TUNNEL_REQUEST,   "ePDG Tunnel Request"},
420
  { OSMO_GSUP_MSGT_EPDG_TUNNEL_ERROR,   "ePDG Tunnel Error"},
421
  { OSMO_GSUP_MSGT_EPDG_TUNNEL_RESULT,    "ePDG Tunnel Result"},
422
  { 0, NULL }
423
};
424
425
static const value_string gsup_rat_types[] = {
426
  { OSMO_GSUP_RAT_UNKNOWN,    "Unknown" },
427
  { OSMO_GSUP_RAT_GERAN_A,    "GERAN (A)" },
428
  { OSMO_GSUP_RAT_UTRAN_IU,   "UTRAN (IU)" },
429
  { OSMO_GSUP_RAT_EUTRAN_SGS,   "EUTRAN (SGS)" },
430
  { 0, NULL }
431
};
432
433
static const value_string gsup_cancel_types[] = {
434
  { OSMO_GSUP_CANCEL_TYPE_UPDATE,   "Update" },
435
  { OSMO_GSUP_CANCEL_TYPE_WITHDRAW, "Withdraw" },
436
  { 0, NULL }
437
};
438
439
static const value_string gsup_cndomain_types[] = {
440
  { OSMO_GSUP_CN_DOMAIN_PS,   "PS" },
441
  { OSMO_GSUP_CN_DOMAIN_CS,   "CS" },
442
  { 0, NULL }
443
};
444
445
static const value_string gsup_session_states[] = {
446
  { OSMO_GSUP_SESSION_STATE_NONE,   "NONE" },
447
  { OSMO_GSUP_SESSION_STATE_BEGIN,  "BEGIN" },
448
  { OSMO_GSUP_SESSION_STATE_CONTINUE, "CONTINUE" },
449
  { OSMO_GSUP_SESSION_STATE_END,    "END" },
450
  { 0, NULL }
451
};
452
453
static const value_string osmo_gsup_sms_sm_rp_oda_types[] = {
454
  { OSMO_GSUP_SMS_SM_RP_ODA_NONE,   "NONE" },
455
  { OSMO_GSUP_SMS_SM_RP_ODA_IMSI,   "IMSI" },
456
  { OSMO_GSUP_SMS_SM_RP_ODA_MSISDN, "MSISDN" },
457
  { OSMO_GSUP_SMS_SM_RP_ODA_SMSC_ADDR,  "SMSC Address" },
458
  { OSMO_GSUP_SMS_SM_RP_ODA_NULL,   "noSM-RP-DA or noSM-RP-OA" },
459
  { 0, NULL }
460
};
461
462
static const value_string osmo_gsup_sms_sm_alert_rsn_types[] = {
463
  { OSMO_GSUP_SMS_SM_ALERT_RSN_NONE,    "NONE" },
464
  { OSMO_GSUP_SMS_SM_ALERT_RSN_MS_PRESENT,  "MS Present" },
465
  { OSMO_GSUP_SMS_SM_ALERT_RSN_MEM_AVAIL,   "Memory Available (SMMA)" },
466
  { 0, NULL }
467
};
468
469
static const value_string gsup_imei_result_types[] = {
470
  { OSMO_GSUP_IMEI_RESULT_ACK,    "ACK" },
471
  { OSMO_GSUP_IMEI_RESULT_NACK,   "NACK" },
472
  { 0, NULL }
473
};
474
475
static const value_string gsup_msg_class_types[] = {
476
  { OSMO_GSUP_MESSAGE_CLASS_UNSET, "unset" },
477
  { OSMO_GSUP_MESSAGE_CLASS_SUBSCRIBER_MANAGEMENT, "Subscriber-Management" },
478
  { OSMO_GSUP_MESSAGE_CLASS_SMS, "SMS" },
479
  { OSMO_GSUP_MESSAGE_CLASS_USSD, "USSD" },
480
  { OSMO_GSUP_MESSAGE_CLASS_INTER_MSC, "Inter-MSC" },
481
  { 0, NULL }
482
};
483
484
static const value_string gsup_an_type_vals[] = {
485
  { OSMO_GSUP_AN_TYPE_BSSAP, "BSSAP" },
486
  { OSMO_GSUP_AN_TYPE_RANAP, "RANAP" },
487
  { 0, NULL }
488
};
489
490
491
static void dissect_ss_info_ie(tvbuff_t *tvb, packet_info *pinfo, unsigned offset, unsigned len, proto_tree *tree)
492
23
{
493
23
  unsigned saved_offset;
494
23
  int8_t appclass;
495
23
  bool pc;
496
23
  bool ind = false;
497
23
  uint32_t component_len = 0;
498
23
  uint32_t header_end_offset;
499
23
  uint32_t header_len;
500
23
  asn1_ctx_t asn1_ctx;
501
23
  tvbuff_t *ss_tvb = NULL;
502
23
  static int comp_type_tag;
503
504
23
  asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, true, pinfo);
505
23
  saved_offset = offset;
506
23
  col_append_str(pinfo->cinfo, COL_PROTOCOL, "/");
507
23
  col_set_fence(pinfo->cinfo, COL_PROTOCOL);
508
81
  while (len > (offset - saved_offset)) {
509
    /* get the length of the component. there can be multiple components in one message */
510
58
    header_end_offset = get_ber_identifier(tvb, offset, &appclass, &pc, &comp_type_tag);
511
58
    header_end_offset = get_ber_length(tvb, header_end_offset, &component_len, &ind);
512
58
    header_len = header_end_offset -offset;
513
58
    component_len += header_len;
514
515
58
    ss_tvb = tvb_new_subset_length(tvb, offset, component_len);
516
58
    col_append_str(pinfo->cinfo, COL_INFO, "(GSM MAP) ");
517
58
    col_set_fence(pinfo->cinfo, COL_INFO);
518
58
    call_dissector(gsm_map_handle, ss_tvb, pinfo, tree);
519
58
    offset += component_len;
520
58
  }
521
23
}
522
523
static void dissect_sm_rp_da_ie(tvbuff_t *tvb, packet_info *pinfo, unsigned offset,
524
        unsigned ie_len, proto_tree *tree)
525
13
{
526
13
  tvbuff_t *addr_tvb;
527
13
  proto_item *ti;
528
13
  uint8_t id_type;
529
530
  /* Identity type is mandatory */
531
13
  if (ie_len < 1) {
532
2
    expert_add_info_format(pinfo, NULL, &ei_sm_rp_da_invalid,
533
2
      "Missing mandatory SM-RP-DA ID type (IE len < 1)");
534
2
    return;
535
2
  }
536
537
  /* Parse ID type */
538
11
  ti = proto_tree_add_item_ret_uint8(tree, hf_gsup_sm_rp_da_id_type, tvb, offset, 1, ENC_NA, &id_type);
539
540
11
  switch (id_type) {
541
1
  case OSMO_GSUP_SMS_SM_RP_ODA_IMSI:
542
1
    dissect_e212_imsi(tvb, pinfo, tree,
543
1
      offset + 1, ie_len - 1, false);
544
1
    break;
545
1
  case OSMO_GSUP_SMS_SM_RP_ODA_MSISDN:
546
1
  case OSMO_GSUP_SMS_SM_RP_ODA_SMSC_ADDR:
547
1
    addr_tvb = tvb_new_subset_length(tvb, offset + 1, ie_len - 1);
548
1
    dissect_gsm_map_msisdn(addr_tvb, pinfo, tree);
549
1
    break;
550
551
  /* Special case for noSM-RP-DA and noSM-RP-OA */
552
1
  case OSMO_GSUP_SMS_SM_RP_ODA_NULL:
553
1
    if (ie_len > 1) {
554
1
      expert_add_info_format(pinfo, ti, &ei_sm_rp_da_invalid,
555
1
        "Unexpected ID length=%u for noSM-RP-DA", ie_len - 1);
556
1
      return;
557
1
    }
558
0
    break;
559
560
4
  case OSMO_GSUP_SMS_SM_RP_ODA_NONE:
561
8
  default:
562
8
    expert_add_info_format(pinfo, ti, &ei_sm_rp_da_invalid,
563
8
      "Unexpected SM-RP-DA ID (type=0x%02x)", id_type);
564
8
    return;
565
11
  }
566
11
}
567
568
static void dissect_sm_rp_oa_ie(tvbuff_t *tvb, packet_info *pinfo, unsigned offset,
569
        unsigned ie_len, proto_tree *tree)
570
14
{
571
14
  tvbuff_t *addr_tvb;
572
14
  proto_item *ti;
573
14
  uint8_t id_type;
574
575
  /* Identity type is mandatory */
576
14
  if (ie_len < 1) {
577
3
    expert_add_info_format(pinfo, NULL, &ei_sm_rp_oa_invalid,
578
3
      "Missing mandatory SM-RP-OA ID type (IE len < 1)");
579
3
    return;
580
3
  }
581
582
  /* Parse ID type */
583
11
  ti = proto_tree_add_item_ret_uint8(tree, hf_gsup_sm_rp_oa_id_type, tvb, offset, 1, ENC_NA, &id_type);
584
585
11
  switch (id_type) {
586
1
  case OSMO_GSUP_SMS_SM_RP_ODA_MSISDN:
587
2
  case OSMO_GSUP_SMS_SM_RP_ODA_SMSC_ADDR:
588
2
    addr_tvb = tvb_new_subset_length(tvb, offset + 1, ie_len - 1);
589
2
    dissect_gsm_map_msisdn(addr_tvb, pinfo, tree);
590
2
    break;
591
592
  /* Special case for noSM-RP-DA and noSM-RP-OA */
593
0
  case OSMO_GSUP_SMS_SM_RP_ODA_NULL:
594
0
    if (ie_len > 1) {
595
0
      expert_add_info_format(pinfo, ti, &ei_sm_rp_oa_invalid,
596
0
        "Unexpected ID length=%u for noSM-RP-OA", ie_len - 1);
597
0
      return;
598
0
    }
599
0
    break;
600
601
0
  case OSMO_GSUP_SMS_SM_RP_ODA_NONE:
602
9
  default:
603
9
    expert_add_info_format(pinfo, ti, &ei_sm_rp_oa_invalid,
604
9
      "Unexpected SM-RP-OA ID (type=0x%02x)", id_type);
605
9
    return;
606
11
  }
607
11
}
608
609
static void dissect_sm_rp_ui_ie(tvbuff_t *tvb, packet_info *pinfo, unsigned offset,
610
        unsigned ie_len, proto_tree *tree, uint8_t msg_type)
611
219
{
612
219
  tvbuff_t *ss_tvb;
613
614
  /* Choose direction: RECV for MO, SENT for MT */
615
219
  switch (msg_type) {
616
0
  case OSMO_GSUP_MSGT_MO_FORWARD_SM_REQUEST:
617
0
  case OSMO_GSUP_MSGT_MO_FORWARD_SM_ERROR:
618
183
  case OSMO_GSUP_MSGT_MO_FORWARD_SM_RESULT:
619
183
    pinfo->p2p_dir = P2P_DIR_RECV;
620
183
    break;
621
0
  case OSMO_GSUP_MSGT_MT_FORWARD_SM_REQUEST:
622
0
  case OSMO_GSUP_MSGT_MT_FORWARD_SM_ERROR:
623
0
  case OSMO_GSUP_MSGT_MT_FORWARD_SM_RESULT:
624
0
    pinfo->p2p_dir = P2P_DIR_SENT;
625
0
    break;
626
36
  default:
627
    /* Just to be sure */
628
36
    break;
629
219
  }
630
631
219
  ss_tvb = tvb_new_subset_length(tvb, offset, ie_len);
632
219
  call_dissector(gsm_sms_handle, ss_tvb, pinfo, tree);
633
219
}
634
635
static void dissect_imei_ie(tvbuff_t *tvb, packet_info *pinfo, unsigned offset,
636
          unsigned ie_len, proto_tree *tree)
637
16
{
638
16
  tvbuff_t *ss_tvb = tvb_new_subset_length(tvb, offset-1, ie_len+1);
639
16
  if(bssap_imei_handle)
640
16
    call_dissector(bssap_imei_handle, ss_tvb, pinfo, tree);
641
16
}
642
643
static void dissect_an_apdu_ie(tvbuff_t *tvb, packet_info *pinfo, unsigned offset,
644
             unsigned ie_len, proto_tree *tree, proto_item *parent_ti)
645
9
{
646
9
  tvbuff_t *ss_tvb = tvb_new_subset_length(tvb, offset+1, ie_len-1);
647
9
  uint32_t an_type;
648
649
9
  proto_tree_add_item_ret_uint(tree, hf_gsup_an_type, tvb, offset, 1, ENC_NA, &an_type);
650
9
  proto_item_append_text(parent_ti, ": %s", val_to_str_const(an_type, gsup_msg_class_types, "unknown"));
651
652
9
  switch (an_type) {
653
1
  case OSMO_GSUP_AN_TYPE_BSSAP:
654
1
    call_dissector(bssap_handle, ss_tvb, pinfo, tree);
655
1
    break;
656
1
  case OSMO_GSUP_AN_TYPE_RANAP:
657
1
    call_dissector(ranap_handle, ss_tvb, pinfo, tree);
658
1
    break;
659
7
  default:
660
7
    proto_tree_add_item(tree, hf_gsup_ie_payload, ss_tvb, 0, -1, ENC_NA);
661
7
    break;
662
9
  }
663
9
}
664
665
static void dissect_name_ie(tvbuff_t *tvb, packet_info *pinfo _U_, unsigned offset,
666
          unsigned ie_len, proto_tree *tree, proto_item *parent_ti, uint8_t tag)
667
21
{
668
21
  proto_item *ti;
669
670
21
  if (show_name_as_text) {
671
21
    uint8_t *str;
672
21
    str = tvb_get_stringzpad(pinfo->pool, tvb, offset, ie_len,  ENC_ASCII|ENC_NA);
673
21
    proto_item_append_text(parent_ti, ": %s", (char *)str);
674
21
  }
675
676
21
  switch (tag) {
677
9
  case OSMO_GSUP_SOURCE_NAME_IE:
678
9
    ti = proto_tree_add_item(tree, hf_gsup_source_name, tvb, offset, ie_len, ENC_NA);
679
9
    if (show_name_as_text) {
680
9
      proto_item_set_hidden(ti);
681
9
      proto_tree_add_item(tree, hf_gsup_source_name_text, tvb, offset, ie_len, ENC_ASCII);
682
9
    }
683
9
    break;
684
7
  case OSMO_GSUP_DESTINATION_NAME_IE:
685
7
    ti = proto_tree_add_item(tree, hf_gsup_destination_name, tvb, offset, ie_len, ENC_NA);
686
7
    if (show_name_as_text) {
687
7
      proto_item_set_hidden(ti);
688
7
      proto_tree_add_item(tree, hf_gsup_destination_name_text, tvb, offset, ie_len, ENC_ASCII);
689
7
    }
690
7
    break;
691
21
  }
692
21
}
693
694
695
static int
696
// NOLINTNEXTLINE(misc-no-recursion)
697
dissect_gsup_tlvs(tvbuff_t *tvb, int base_offs, int length, packet_info *pinfo, proto_tree *tree,
698
      proto_item *gsup_ti, uint8_t msg_type)
699
485
{
700
485
  int offset = base_offs;
701
702
4.48k
  while (offset - base_offs < length) {
703
4.41k
    uint8_t tag;
704
4.41k
    uint8_t len;
705
4.41k
    proto_item *ti;
706
4.41k
    proto_tree *att_tree;
707
4.41k
    const char *apn;
708
4.41k
    const char *str;
709
4.41k
    int apn_len;
710
4.41k
    uint32_t ui32;
711
4.41k
    uint8_t i;
712
4.41k
    tvbuff_t *subset_tvb;
713
714
4.41k
    tag = tvb_get_uint8(tvb, offset);
715
4.41k
    offset++;
716
717
4.41k
    len = tvb_get_uint8(tvb, offset);
718
4.41k
    offset++;
719
720
4.41k
    if (offset - base_offs + len > length) {
721
117
      expert_add_info(pinfo, gsup_ti, &ei_gsup_ie_len_invalid);
722
117
      return offset - 2;
723
117
    }
724
725
4.29k
    att_tree = proto_tree_add_subtree_format(tree, tvb, offset-2, len+2, ett_gsup_ie, &ti,
726
4.29k
            "IE: %s",
727
4.29k
            val_to_str(pinfo->pool, tag, gsup_iei_types, "Unknown 0x%02x"));
728
4.29k
    proto_tree_add_item(att_tree, hf_gsup_iei, tvb, offset-2, 1, ENC_BIG_ENDIAN);
729
4.29k
    proto_tree_add_uint(att_tree, hf_gsup_ie_len, tvb, offset-1, 1, len);
730
731
4.29k
    increment_dissection_depth(pinfo);
732
4.29k
    switch (tag) {
733
    /* Nested TLVs */
734
149
    case OSMO_GSUP_AUTH_TUPLE_IE:
735
196
    case OSMO_GSUP_PDP_INFO_IE:
736
196
      dissect_gsup_tlvs(tvb, offset, len, pinfo, att_tree, gsup_ti, msg_type);
737
196
      break;
738
    /* Normal IEs */
739
20
    case OSMO_GSUP_RAND_IE:
740
20
      proto_tree_add_item(att_tree, hf_gsup_rand, tvb, offset, len, ENC_NA);
741
20
      break;
742
29
    case OSMO_GSUP_SRES_IE:
743
29
      proto_tree_add_item(att_tree, hf_gsup_sres, tvb, offset, len, ENC_NA);
744
29
      break;
745
19
    case OSMO_GSUP_KC_IE:
746
19
      proto_tree_add_item(att_tree, hf_gsup_kc, tvb, offset, len, ENC_NA);
747
19
      break;
748
5
    case OSMO_GSUP_IK_IE:
749
5
      proto_tree_add_item(att_tree, hf_gsup_ik, tvb, offset, len, ENC_NA);
750
5
      break;
751
12
    case OSMO_GSUP_CK_IE:
752
12
      proto_tree_add_item(att_tree, hf_gsup_ck, tvb, offset, len, ENC_NA);
753
12
      break;
754
41
    case OSMO_GSUP_AUTN_IE:
755
41
      proto_tree_add_item(att_tree, hf_gsup_autn, tvb, offset, len, ENC_NA);
756
41
      break;
757
11
    case OSMO_GSUP_AUTS_IE:
758
11
      proto_tree_add_item(att_tree, hf_gsup_auts, tvb, offset, len, ENC_NA);
759
11
      break;
760
3
    case OSMO_GSUP_RES_IE:
761
3
      proto_tree_add_item(att_tree, hf_gsup_res, tvb, offset, len, ENC_NA);
762
3
      break;
763
15
    case OSMO_GSUP_CN_DOMAIN_IE:
764
15
      proto_tree_add_item(att_tree, hf_gsup_cn_domain, tvb, offset, len, ENC_NA);
765
15
      break;
766
32
    case OSMO_GSUP_SUPPORTED_RAT_TYPES_IE:
767
1.19k
      for (i = 0; i < len; i++) {
768
1.16k
        proto_tree_add_item(att_tree, hf_gsup_supported_rat_type,
769
1.16k
                tvb, offset + i, 1, ENC_NA);
770
1.16k
      }
771
32
      break;
772
11
    case OSMO_GSUP_CURRENT_RAT_TYPE_IE:
773
11
      proto_tree_add_item(att_tree, hf_gsup_current_rat_type, tvb, offset, len, ENC_NA);
774
11
      break;
775
70
    case OSMO_GSUP_CANCEL_TYPE_IE:
776
70
      proto_tree_add_item(att_tree, hf_gsup_cancel_type, tvb, offset, len, ENC_NA);
777
70
      break;
778
592
    case OSMO_GSUP_IMSI_IE:
779
592
      str = dissect_e212_imsi(tvb, pinfo, att_tree, offset, len, false);
780
592
      proto_item_append_text(ti, ", %s", str);
781
592
      proto_item_append_text(gsup_ti, ", IMSI: %s", str);
782
592
      break;
783
149
    case OSMO_GSUP_MSISDN_IE:
784
149
      str = dissect_e164_msisdn(tvb, pinfo, att_tree, offset+1, len-1, E164_ENC_BCD);
785
149
      proto_item_append_text(ti, ", %s", str);
786
149
      proto_item_append_text(gsup_ti, ", MSISDN: %s", str);
787
149
      break;
788
12
    case OSMO_GSUP_ACCESS_POINT_NAME_IE:
789
12
      if (len == 1) {
790
5
        uint8_t ch = tvb_get_uint8(tvb, offset);
791
5
        proto_tree_add_item(att_tree, hf_gsup_ie_payload, tvb, offset, len, ENC_NA);
792
5
        if (ch == '*')
793
0
          proto_item_append_text(ti, ", '*' (Wildcard)");
794
7
      } else {
795
7
                                char *name_out;
796
797
7
        get_dns_name(pinfo->pool, tvb, offset, len, 0, &apn, &apn_len);
798
7
        name_out = format_text(pinfo->pool, apn, apn_len);
799
7
        proto_tree_add_string(att_tree, hf_gsup_apn, tvb, offset, len, name_out);
800
7
        proto_item_append_text(ti, ", %s", name_out);
801
7
      }
802
12
      break;
803
34
    case OSMO_GSUP_PDP_CONTEXT_ID_IE:
804
34
      proto_tree_add_item(att_tree, hf_gsup_pdp_context_id, tvb, offset, len, ENC_NA);
805
34
      break;
806
42
    case OSMO_GSUP_CHARG_CHAR_IE:
807
42
      proto_tree_add_item(att_tree, hf_gsup_charg_char, tvb, offset, len, ENC_ASCII);
808
42
      break;
809
48
    case OSMO_GSUP_PCO_IE:
810
48
      switch (msg_type) {
811
0
      case OSMO_GSUP_MSGT_EPDG_TUNNEL_REQUEST:
812
        /* PCO options as MS to network direction */
813
0
        pinfo->link_dir = P2P_DIR_UL;
814
0
        break;
815
0
      case OSMO_GSUP_MSGT_EPDG_TUNNEL_ERROR:
816
0
      case OSMO_GSUP_MSGT_EPDG_TUNNEL_RESULT:
817
        /* PCO options as Network to MS direction: */
818
0
        pinfo->link_dir = P2P_DIR_DL;
819
0
        break;
820
48
      default:
821
48
        break;
822
48
      }
823
48
      subset_tvb = tvb_new_subset_length(tvb, offset, len);
824
48
      de_sm_pco(subset_tvb, att_tree, pinfo, 0, len, NULL, 0);
825
48
      break;
826
85
    case OSMO_GSUP_CAUSE_IE:
827
85
      proto_tree_add_item(att_tree, hf_gsup_cause, tvb, offset, len, ENC_NA);
828
85
      break;
829
    /* boolean flags: either they're present or not */
830
110
    case OSMO_GSUP_PDP_INFO_COMPL_IE:
831
110
      proto_tree_add_item(att_tree, hf_gsup_pdp_info_compl, tvb, offset, len, ENC_NA);
832
110
      break;
833
47
    case OSMO_GSUP_FREEZE_PTMSI_IE:
834
47
      proto_tree_add_item(att_tree, hf_gsup_freeze_ptmsi, tvb, offset, len, ENC_NA);
835
47
      break;
836
19
    case OSMO_GSUP_SESSION_ID_IE:
837
19
      proto_tree_add_item(att_tree, hf_gsup_session_id, tvb, offset, len, ENC_BIG_ENDIAN);
838
19
      break;
839
19
    case OSMO_GSUP_SESSION_STATE_IE:
840
19
      proto_tree_add_item(att_tree, hf_gsup_session_state, tvb, offset, len, ENC_NA);
841
19
      break;
842
23
    case OSMO_GSUP_SS_INFO_IE:
843
23
      dissect_ss_info_ie(tvb, pinfo, offset, len, att_tree);
844
23
      break;
845
12
    case OSMO_GSUP_SM_RP_MR_IE:
846
12
      proto_tree_add_item(att_tree, hf_gsup_sm_rp_mr, tvb, offset, len, ENC_NA);
847
12
      break;
848
13
    case OSMO_GSUP_SM_RP_DA_IE:
849
13
      dissect_sm_rp_da_ie(tvb, pinfo, offset, len, att_tree);
850
13
      break;
851
14
    case OSMO_GSUP_SM_RP_OA_IE:
852
14
      dissect_sm_rp_oa_ie(tvb, pinfo, offset, len, att_tree);
853
14
      break;
854
219
    case OSMO_GSUP_SM_RP_UI_IE:
855
219
      dissect_sm_rp_ui_ie(tvb, pinfo, offset, len, att_tree, msg_type);
856
219
      break;
857
3
    case OSMO_GSUP_SM_RP_CAUSE_IE:
858
3
      proto_tree_add_item(att_tree, hf_gsup_sm_rp_cause, tvb, offset, len, ENC_NA);
859
3
      break;
860
12
    case OSMO_GSUP_SM_RP_MMS_IE:
861
12
      proto_tree_add_item(att_tree, hf_gsup_sm_rp_mms, tvb, offset, len, ENC_NA);
862
12
      break;
863
10
    case OSMO_GSUP_SM_ALERT_RSN_IE:
864
10
      proto_tree_add_item(att_tree, hf_gsup_sm_alert_rsn, tvb, offset, len, ENC_NA);
865
10
      break;
866
16
    case OSMO_GSUP_IMEI_IE:
867
16
      dissect_imei_ie(tvb, pinfo, offset, len, att_tree);
868
16
      break;
869
5
    case OSMO_GSUP_IMEI_RESULT_IE:
870
5
      proto_tree_add_item(att_tree, hf_gsup_imei_result, tvb, offset, len, ENC_NA);
871
5
      break;
872
13
    case OSMO_GSUP_NUM_VECTORS_REQ_IE:
873
13
      proto_tree_add_item(att_tree, hf_gsup_num_vectors_req, tvb, offset, len, ENC_NA);
874
13
      break;
875
136
    case OSMO_GSUP_MESSAGE_CLASS_IE:
876
136
      proto_tree_add_item_ret_uint(att_tree, hf_gsup_msg_class, tvb, offset, len, ENC_NA, &ui32);
877
136
      proto_item_append_text(ti, ": %s", val_to_str_const(ui32, gsup_msg_class_types, "unknown"));
878
136
      break;
879
9
    case OSMO_GSUP_AN_APDU_IE:
880
9
      dissect_an_apdu_ie(tvb, pinfo, offset, len, att_tree, ti);
881
9
      break;
882
12
    case OSMO_GSUP_SOURCE_NAME_IE:
883
21
    case OSMO_GSUP_DESTINATION_NAME_IE:
884
21
      dissect_name_ie(tvb, pinfo, offset, len, att_tree, ti, tag);
885
21
      break;
886
10
    case OSMO_GSUP_CAUSE_RR_IE:
887
10
      de_rr_cause(tvb, att_tree, pinfo, offset, len, NULL, 0);
888
10
      break;
889
17
    case OSMO_GSUP_CAUSE_BSSAP_IE:
890
17
      bssmap_dissect_cause(tvb, att_tree, pinfo, offset, len, NULL, 0);
891
17
      break;
892
11
    case OSMO_GSUP_CAUSE_SM_IE:
893
11
      de_sm_cause(tvb, att_tree, pinfo, offset, len, NULL, 0);
894
11
      break;
895
42
    case OSMO_GSUP_PDP_ADDRESS_IE:
896
42
      proto_tree_add_bits_item(att_tree, hf_gsup_spare_bits, tvb, (offset << 3), 4, ENC_BIG_ENDIAN);
897
42
      proto_tree_add_item(att_tree, hf_gsup_pdp_addr_type_org, tvb, offset, 1, ENC_BIG_ENDIAN);
898
42
      proto_tree_add_item(att_tree, hf_gsup_pdp_addr_type_nr, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
899
42
      if (len > 2) {
900
22
        switch (tvb_get_uint8(tvb, offset) & 0x0f) {
901
16
        case 0x01: /* IETF */
902
16
          switch (tvb_get_uint8(tvb, offset + 1)) {
903
0
          case 0x21:
904
0
            proto_tree_add_item(att_tree, hf_gsup_pdp_addr_v4, tvb, offset + 3, 4, ENC_BIG_ENDIAN);
905
0
            break;
906
0
          case 0x57:
907
0
            proto_tree_add_item(att_tree, hf_gsup_pdp_addr_v6, tvb, offset + 3, 16, ENC_NA);
908
0
            break;
909
0
          case 0x8d:
910
0
            proto_tree_add_item(att_tree, hf_gsup_pdp_addr_v4, tvb, offset + 3, 4, ENC_BIG_ENDIAN);
911
0
            proto_tree_add_item(att_tree, hf_gsup_pdp_addr_v6, tvb, offset + 7, 16, ENC_NA);
912
0
            break;
913
16
          default:
914
16
            break;
915
16
          }
916
16
          break;
917
16
        default:
918
6
          break;
919
22
        }
920
22
      }
921
42
      break;
922
42
    case OSMO_GSUP_HLR_NUMBER_IE:
923
32
    case OSMO_GSUP_PDP_QOS_IE:
924
2.04k
    default:
925
      /* Unknown/unsupported IE: Print raw payload in addition to IEI + Length printed above */
926
2.04k
      proto_tree_add_item(att_tree, hf_gsup_ie_payload, tvb, offset, len, ENC_NA);
927
2.04k
      break;
928
4.29k
    }
929
4.00k
    decrement_dissection_depth(pinfo);
930
931
4.00k
    offset += len;
932
4.00k
  }
933
934
75
  return offset;
935
485
}
936
937
static int
938
dissect_gsup(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
939
289
{
940
289
  int len, offset = 0;
941
289
  proto_item *ti;
942
289
  proto_tree *gsup_tree = NULL;
943
289
  uint8_t msg_type;
944
289
  const char *str;
945
946
947
289
  len = tvb_reported_length(tvb);
948
289
  msg_type = tvb_get_uint8(tvb, offset + 0);
949
950
289
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "GSUP");
951
952
289
  col_clear(pinfo->cinfo, COL_INFO);
953
289
  str = val_to_str(pinfo->pool, msg_type, gsup_msg_types, "Unknown GSUP Message Type 0x%02x");
954
289
  col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", str);
955
956
289
  ti = proto_tree_add_protocol_format(tree, proto_gsup, tvb, 0, len, "GSUP %s", str);
957
289
  gsup_tree = proto_item_add_subtree(ti, ett_gsup);
958
959
289
  proto_tree_add_item(gsup_tree, hf_gsup_msg_type,
960
289
          tvb, offset, 1, ENC_BIG_ENDIAN);
961
289
  offset++;
962
963
289
  dissect_gsup_tlvs(tvb, offset, tvb_reported_length_remaining(tvb, offset), pinfo,
964
289
        gsup_tree, ti, msg_type);
965
966
289
  return tvb_captured_length(tvb);
967
289
}
968
969
void
970
proto_register_gsup(void)
971
16
{
972
16
  static const value_string pdp_type[] = {
973
16
    {0x00, "X.25"},
974
16
    {0x01, "PPP"},
975
16
    {0x02, "OSP:IHOSS"},
976
16
    {0x21, "IPv4"},
977
16
    {0x57, "IPv6"},
978
16
    {0x8d, "IPv4v6"},
979
16
    {0, NULL}
980
16
  };
981
982
16
  static const value_string pdp_org_type[] = {
983
16
    {0, "ETSI"},
984
16
    {1, "IETF"},
985
16
    {0, NULL}
986
16
  };
987
988
16
  static hf_register_info hf[] = {
989
16
    { &hf_gsup_msg_type, { "Message Type", "gsup.msg_type",
990
16
      FT_UINT8, BASE_DEC, VALS(gsup_msg_types), 0, NULL, HFILL } },
991
16
    { &hf_gsup_iei, { "Information Element Identifier", "gsup.ie.iei",
992
16
      FT_UINT8, BASE_DEC, VALS(gsup_iei_types), 0, NULL, HFILL } },
993
16
    { &hf_gsup_ie_len, { "Information Element Length", "gsup.ie.len",
994
16
      FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } },
995
16
    { &hf_gsup_ie_payload, { "Information Element Payload", "gsup.ie.payload",
996
16
      FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL } },
997
998
16
    { &hf_gsup_rand, { "RAND", "gsup.rand",
999
16
      FT_BYTES, BASE_NONE, NULL, 0, "Random Challenge", HFILL } },
1000
16
    { &hf_gsup_sres, { "SRES", "gsup.sres",
1001
16
      FT_BYTES, BASE_NONE, NULL, 0, "GSM/GPRS Authentication Result SRES Value", HFILL } },
1002
16
    { &hf_gsup_kc, { "Kc", "gsup.kc",
1003
16
      FT_BYTES, BASE_NONE, NULL, 0, "GSM/GPRS Ciphering Key", HFILL } },
1004
16
    { &hf_gsup_ik, { "IK", "gsup.ik",
1005
16
      FT_BYTES, BASE_NONE, NULL, 0, "UMTS Integrity Protection Key", HFILL } },
1006
16
    { &hf_gsup_ck, { "CK", "gsup.ck",
1007
16
      FT_BYTES, BASE_NONE, NULL, 0, "UMTS Ciphering Key", HFILL } },
1008
16
    { &hf_gsup_autn, { "AUTN", "gsup.autn",
1009
16
      FT_BYTES, BASE_NONE, NULL, 0, "UMTS Authentication Nonce", HFILL } },
1010
16
    { &hf_gsup_auts, { "AUTN", "gsup.auts",
1011
16
      FT_BYTES, BASE_NONE, NULL, 0, "UMTS Authentication Sync", HFILL } },
1012
16
    { &hf_gsup_res, { "RES", "gsup.res",
1013
16
      FT_BYTES, BASE_NONE, NULL, 0, "UMTS Authentication Result", HFILL } },
1014
1015
16
    { &hf_gsup_cn_domain, { "CN Domain Indicator", "gsup.cn_domain",
1016
16
      FT_UINT8, BASE_DEC, VALS(gsup_cndomain_types), 0, NULL, HFILL } },
1017
16
    { &hf_gsup_supported_rat_type, { "Supported RAT Type", "gsup.supported_rat_type",
1018
16
      FT_UINT8, BASE_DEC, VALS(gsup_rat_types), 0, NULL, HFILL } },
1019
16
    { &hf_gsup_current_rat_type, { "Current RAT Type", "gsup.current_rat_type",
1020
16
      FT_UINT8, BASE_DEC, VALS(gsup_rat_types), 0, NULL, HFILL } },
1021
16
    { &hf_gsup_cancel_type, { "Cancel Type", "gsup.cancel_type",
1022
16
      FT_UINT8, BASE_DEC, VALS(gsup_cancel_types), 0, NULL, HFILL } },
1023
16
    { &hf_gsup_pdp_info_compl, { "PDP Information Complete", "gsup.pdp_info_compl",
1024
16
      FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } },
1025
16
    { &hf_gsup_freeze_ptmsi, { "Freeze P-TMSI", "gsup.freeze_ptmsi",
1026
16
      FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } },
1027
16
    { &hf_gsup_apn, { "APN", "gsup.apn",
1028
16
      FT_STRING, BASE_NONE, NULL, 0, "Access Point Name", HFILL } },
1029
16
    { &hf_gsup_pdp_context_id, { "PDP Context ID", "gsup.pdp_context_id",
1030
16
      FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } },
1031
16
    { &hf_gsup_charg_char, { "Charging Character", "gsup.charg_char",
1032
16
      FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
1033
16
    { &hf_gsup_cause, { "Cause", "gsup.cause",
1034
16
      FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } },
1035
16
    { &hf_gsup_session_id, { "Session ID", "gsup.session_id",
1036
16
      FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } },
1037
16
    { &hf_gsup_session_state, { "Session State", "gsup.session_state",
1038
16
      FT_UINT8, BASE_DEC, VALS(gsup_session_states), 0, NULL, HFILL } },
1039
16
    { &hf_gsup_sm_rp_mr, { "SM-RP-MR (Message Reference)", "gsup.sm_rp_mr",
1040
16
      FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } },
1041
16
    { &hf_gsup_sm_rp_da_id_type, { "Address Type", "gsup.sm_rp_da.addr_type",
1042
16
      FT_UINT8, BASE_DEC, VALS(osmo_gsup_sms_sm_rp_oda_types), 0, NULL, HFILL } },
1043
16
    { &hf_gsup_sm_rp_oa_id_type, { "Address Type", "gsup.sm_rp_oa.addr_type",
1044
16
      FT_UINT8, BASE_DEC, VALS(osmo_gsup_sms_sm_rp_oda_types), 0, NULL, HFILL } },
1045
16
    { &hf_gsup_sm_rp_cause, { "SM-RP Cause", "gsup.sm_rp.cause",
1046
16
      FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } },
1047
16
    { &hf_gsup_sm_rp_mms, { "More Messages to Send", "gsup.sm_rp.mms",
1048
16
      FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } },
1049
16
    { &hf_gsup_sm_alert_rsn, { "SM Alert Reason", "gsup.sm_alert_rsn",
1050
16
      FT_UINT8, BASE_DEC, VALS(osmo_gsup_sms_sm_alert_rsn_types), 0, NULL, HFILL } },
1051
16
    { &hf_gsup_imei_result, { "IMEI Check Result", "gsup.imei_check_res",
1052
16
      FT_UINT8, BASE_DEC, VALS(gsup_imei_result_types), 0, NULL, HFILL } },
1053
16
    { &hf_gsup_num_vectors_req, { "Number of Vectors Requested", "gsup.num_vectors_req",
1054
16
      FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } },
1055
16
    { &hf_gsup_msg_class, { "Message Class", "gsup.msg_class",
1056
16
      FT_UINT8, BASE_DEC, VALS(gsup_msg_class_types), 0, NULL, HFILL } },
1057
16
    { &hf_gsup_an_type, { "Access Network Type", "gsup.an_type",
1058
16
      FT_UINT8, BASE_DEC, VALS(gsup_an_type_vals), 0, NULL, HFILL } },
1059
16
    { &hf_gsup_source_name, { "Source Name", "gsup.source_name",
1060
16
      FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL } },
1061
16
    { &hf_gsup_source_name_text, { "Source Name (Text)", "gsup.source_name.text",
1062
16
      FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
1063
16
    { &hf_gsup_destination_name, { "Destination Name", "gsup.dest_name",
1064
16
      FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL } },
1065
16
    { &hf_gsup_destination_name_text, { "Destination Name (Text)", "gsup.dest_name.text",
1066
16
      FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
1067
16
    { &hf_gsup_spare_bits, { "Spare bit(s)", "gsup.spare_bits",
1068
16
      FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1069
16
    { &hf_gsup_pdp_addr_type_org, { "PDP organization", "gsup.pdp_organization",
1070
16
      FT_UINT8, BASE_DEC, VALS(pdp_org_type), 0x0F, NULL, HFILL }},
1071
16
    { &hf_gsup_pdp_addr_type_nr, { "PDP type", "gsup.pdp_type",
1072
16
      FT_UINT8, BASE_DEC, VALS(pdp_type), 0x0, NULL, HFILL }},
1073
16
    { &hf_gsup_pdp_addr_v4, { "PDP address", "gsup.pdp_address.ipv4",
1074
16
      FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1075
16
    { &hf_gsup_pdp_addr_v6, { "PDP address", "gsup.pdp_address.ipv6",
1076
16
      FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1077
16
  };
1078
16
  static int *ett[] = {
1079
16
    &ett_gsup,
1080
16
    &ett_gsup_ie,
1081
16
  };
1082
1083
16
  expert_module_t *expert_gsup;
1084
16
  module_t *module_gsup;
1085
1086
16
  static ei_register_info ei[] = {
1087
16
    { &ei_sm_rp_da_invalid,
1088
16
      { "gsup.sm_rp_da.invalid", PI_PROTOCOL, PI_ERROR,
1089
16
        "Malformed SM-RP-DA IE", EXPFILL } },
1090
16
    { &ei_sm_rp_oa_invalid,
1091
16
      { "gsup.sm_rp_oa.invalid", PI_PROTOCOL, PI_ERROR,
1092
16
        "Malformed SM-RP-OA IE", EXPFILL } },
1093
16
    { &ei_gsup_ie_len_invalid,
1094
16
      { "gsup.ie.len.invalid", PI_PROTOCOL, PI_ERROR,
1095
16
        "Invalid Information Element Length", EXPFILL } },
1096
16
  };
1097
1098
16
  proto_gsup = proto_register_protocol("Osmocom General Subscriber Update Protocol", "GSUP", "gsup");
1099
16
  proto_register_field_array(proto_gsup, hf, array_length(hf));
1100
16
  proto_register_subtree_array(ett, array_length(ett));
1101
1102
16
  gsup_handle = register_dissector("gsup", dissect_gsup, proto_gsup);
1103
1104
16
  expert_gsup = expert_register_protocol(proto_gsup);
1105
16
  expert_register_field_array(expert_gsup, ei, array_length(ei));
1106
1107
16
  module_gsup = prefs_register_protocol(proto_gsup, NULL);
1108
16
  prefs_register_bool_preference(module_gsup,
1109
16
      "show_name_as_text",
1110
16
      "Show Names as text",
1111
16
      "Show GSUP Source/Destination names as text in the Packet Details pane",
1112
16
      &show_name_as_text);
1113
16
}
1114
1115
void
1116
proto_reg_handoff_gsup(void)
1117
16
{
1118
16
  dissector_add_uint_with_preference("ipa.osmo.protocol", IPAC_PROTO_EXT_GSUP, gsup_handle);
1119
16
  gsm_map_handle = find_dissector_add_dependency("gsm_map", proto_gsup);
1120
16
  gsm_sms_handle = find_dissector_add_dependency("gsm_sms", proto_gsup);
1121
16
  bssap_imei_handle = find_dissector_add_dependency("bssap.imei", proto_gsup);
1122
16
  bssap_handle = find_dissector_add_dependency("bssap", proto_gsup);
1123
16
  ranap_handle = find_dissector_add_dependency("ranap", proto_gsup);
1124
16
}
1125
1126
/*
1127
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
1128
 *
1129
 * Local variables:
1130
 * c-basic-offset: 8
1131
 * tab-width: 8
1132
 * indent-tabs-mode: t
1133
 * End:
1134
 *
1135
 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1136
 * :indentSize=8:tabSize=8:noTabs=false:
1137
 */