blob: 87c68842f6ffdbebddd140cef938d88fd4b0c2dc [file] [log] [blame]
Harald Welte288be162010-05-01 16:48:27 +02001/*
Harald Welte89837d42016-05-06 23:28:11 +02002 * (C) 2010-2016 by Harald Welte <laforge@gnumonks.org>
Harald Welte288be162010-05-01 16:48:27 +02003 * (C) 2010 by On-Waves
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02004 * (C) 2015 by Holger Hans Peter Freyther
Harald Welte288be162010-05-01 16:48:27 +02005 * All Rights Reserved
6 *
7 * This program is free software; you can redistribute it and/or modify
Harald Welte9af6ddf2011-01-01 15:25:50 +01008 * it under the terms of the GNU Affero General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
Harald Welte288be162010-05-01 16:48:27 +020010 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Harald Welte9af6ddf2011-01-01 15:25:50 +010015 * GNU Affero General Public License for more details.
Harald Welte288be162010-05-01 16:48:27 +020016 *
Harald Welte9af6ddf2011-01-01 15:25:50 +010017 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
Harald Welte288be162010-05-01 16:48:27 +020019 *
20 */
21
Harald Welte288be162010-05-01 16:48:27 +020022#include <sys/socket.h>
23#include <netinet/in.h>
24#include <arpa/inet.h>
Jacob Erlbeck207f4a52014-11-11 14:01:48 +010025#include <time.h>
Pau Espin Pedrolfa120102018-07-09 20:37:47 +020026#include <inttypes.h>
Harald Welte288be162010-05-01 16:48:27 +020027
Pablo Neira Ayuso136f4532011-03-22 16:47:59 +010028#include <osmocom/core/talloc.h>
29#include <osmocom/core/utils.h>
30#include <osmocom/core/rate_ctr.h>
Harald Welte53373bc2016-04-20 17:11:43 +020031#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
Harald Welte7e82b742017-08-12 13:43:54 +020032#include <osmocom/gsm/apn.h>
Harald Welte288be162010-05-01 16:48:27 +020033
Neels Hofmeyr396f2e62017-09-04 15:13:25 +020034#include <osmocom/sgsn/debug.h>
35#include <osmocom/sgsn/sgsn.h>
Harald Welteea34a4e2012-06-16 14:59:56 +080036#include <osmocom/gprs/gprs_ns.h>
Alexander Couzensc503f0a2018-08-07 17:50:04 +020037#include <osmocom/sgsn/gprs_gmm.h>
Neels Hofmeyr396f2e62017-09-04 15:13:25 +020038#include <osmocom/sgsn/gprs_sgsn.h>
39#include <osmocom/sgsn/vty.h>
40#include <osmocom/sgsn/gsup_client.h>
Harald Welte288be162010-05-01 16:48:27 +020041
Harald Welte4b037e42010-05-19 19:45:32 +020042#include <osmocom/vty/command.h>
43#include <osmocom/vty/vty.h>
Pablo Neira Ayuso6110a3f2011-03-28 19:35:00 +020044#include <osmocom/vty/misc.h>
Max93408ae2016-06-28 14:10:16 +020045#include <osmocom/crypt/gprs_cipher.h>
Jacob Erlbeck80547992014-12-19 19:19:46 +010046#include <osmocom/abis/ipa.h>
47
Alexander Couzensc503f0a2018-08-07 17:50:04 +020048#include <osmocom/gprs/gprs_bssgp.h>
49
Harald Welted193cb32010-05-17 22:58:03 +020050#include <pdp.h>
Maxbaabc682017-10-20 13:39:57 +020051#include <gtp.h>
Harald Welted193cb32010-05-17 22:58:03 +020052
Neels Hofmeyr2188a772016-05-20 21:59:55 +020053#include "../../bscconfig.h"
54
55#ifdef BUILD_IU
Neels Hofmeyra7a39472017-07-05 15:19:52 +020056#include <osmocom/ranap/iu_client.h>
Neels Hofmeyr2188a772016-05-20 21:59:55 +020057#endif
58
Neels Hofmeyree6cfdc2017-07-13 02:03:50 +020059extern void *tall_bsc_ctx;
60
Harald Welte288be162010-05-01 16:48:27 +020061static struct sgsn_config *g_cfg = NULL;
62
Jacob Erlbeck106f5472014-11-04 10:08:37 +010063const struct value_string sgsn_auth_pol_strs[] = {
64 { SGSN_AUTH_POLICY_OPEN, "accept-all" },
65 { SGSN_AUTH_POLICY_CLOSED, "closed" },
66 { SGSN_AUTH_POLICY_ACL_ONLY, "acl-only" },
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +010067 { SGSN_AUTH_POLICY_REMOTE, "remote" },
Jacob Erlbeck106f5472014-11-04 10:08:37 +010068 { 0, NULL }
69};
70
Harald Welte94508822015-08-15 19:08:21 +020071/* Section 11.2.2 / Table 11.3a GPRS Mobility management timers – MS side */
72#define GSM0408_T3312_SECS (10*60) /* periodic RAU interval, default 54min */
73
74/* Section 11.2.2 / Table 11.4 MM timers netwokr side */
75#define GSM0408_T3322_SECS 6 /* DETACH_REQ -> DETACH_ACC */
76#define GSM0408_T3350_SECS 6 /* waiting for ATT/RAU/TMSI COMPL */
77#define GSM0408_T3360_SECS 6 /* waiting for AUTH/CIPH RESP */
78#define GSM0408_T3370_SECS 6 /* waiting for ID RESP */
79
Alexander Couzens5ba6fb32017-01-31 18:04:27 +010080/* Section 11.2.2 / Table 11.4a MM timers network side */
Harald Welte94508822015-08-15 19:08:21 +020081#define GSM0408_T3313_SECS 30 /* waiting for paging response */
82#define GSM0408_T3314_SECS 44 /* force to STBY on expiry, Ready timer */
83#define GSM0408_T3316_SECS 44
84
85/* Section 11.3 / Table 11.2d Timers of Session Management - network side */
86#define GSM0408_T3385_SECS 8 /* wait for ACT PDP CTX REQ */
87#define GSM0408_T3386_SECS 8 /* wait for MODIFY PDP CTX ACK */
88#define GSM0408_T3395_SECS 8 /* wait for DEACT PDP CTX ACK */
89#define GSM0408_T3397_SECS 8 /* wait for DEACT AA PDP CTX ACK */
90
91#define DECLARE_TIMER(number, doc) \
92 DEFUN(cfg_sgsn_T##number, \
93 cfg_sgsn_T##number##_cmd, \
94 "timer t" #number " <0-65535>", \
95 "Configure GPRS Timers\n" \
Holger Hans Peter Freytherfe60cfb2015-11-02 12:55:07 +010096 doc "\nTimer Value in seconds\n") \
Harald Welte94508822015-08-15 19:08:21 +020097{ \
98 int value = atoi(argv[0]); \
99 \
100 if (value < 0 || value > 65535) { \
101 vty_out(vty, "Timer value %s out of range.%s", \
102 argv[0], VTY_NEWLINE); \
103 return CMD_WARNING; \
104 } \
105 \
106 g_cfg->timers.T##number = value; \
107 return CMD_SUCCESS; \
108}
109
110DECLARE_TIMER(3312, "Periodic RA Update timer (s)")
Neels Hofmeyr65482c92015-10-19 14:37:12 +0200111DECLARE_TIMER(3322, "Detach request -> accept timer (s)")
Harald Welte94508822015-08-15 19:08:21 +0200112DECLARE_TIMER(3350, "Waiting for ATT/RAU/TMSI_COMPL timer (s)")
113DECLARE_TIMER(3360, "Waiting for AUTH/CIPH response timer (s)")
114DECLARE_TIMER(3370, "Waiting for IDENTITY response timer (s)")
115
116DECLARE_TIMER(3313, "Waiting for paging response timer (s)")
117DECLARE_TIMER(3314, "Force to STANDBY on expiry timer (s)")
Holger Hans Peter Freytherfe60cfb2015-11-02 12:55:07 +0100118DECLARE_TIMER(3316, "AA-Ready timer (s)")
Harald Welte94508822015-08-15 19:08:21 +0200119
120DECLARE_TIMER(3385, "Wait for ACT PDP CTX REQ timer (s)")
121DECLARE_TIMER(3386, "Wait for MODIFY PDP CTX ACK timer (s)")
122DECLARE_TIMER(3395, "Wait for DEACT PDP CTX ACK timer (s)")
123DECLARE_TIMER(3397, "Wait for DEACT AA PDP CTX ACK timer (s)")
124
Holger Hans Peter Freythera2730302014-03-23 18:08:26 +0100125char *gprs_pdpaddr2str(uint8_t *pdpa, uint8_t len)
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200126{
127 static char str[INET6_ADDRSTRLEN + 10];
128
129 if (!pdpa || len < 2)
130 return "none";
131
132 switch (pdpa[0] & 0x0f) {
133 case PDP_TYPE_ORG_IETF:
134 switch (pdpa[1]) {
135 case PDP_TYPE_N_IETF_IPv4:
136 if (len < 2 + 4)
137 break;
138 strcpy(str, "IPv4 ");
139 inet_ntop(AF_INET, pdpa+2, str+5, sizeof(str)-5);
140 return str;
141 case PDP_TYPE_N_IETF_IPv6:
142 if (len < 2 + 8)
143 break;
144 strcpy(str, "IPv6 ");
145 inet_ntop(AF_INET6, pdpa+2, str+5, sizeof(str)-5);
146 return str;
147 default:
148 break;
149 }
150 break;
151 case PDP_TYPE_ORG_ETSI:
152 if (pdpa[1] == PDP_TYPE_N_ETSI_PPP)
153 return "PPP";
154 break;
155 default:
156 break;
157 }
158
159 return "invalid";
160}
161
Harald Welte288be162010-05-01 16:48:27 +0200162static struct cmd_node sgsn_node = {
163 SGSN_NODE,
Harald Welte570ce242012-08-17 13:16:10 +0200164 "%s(config-sgsn)# ",
Harald Welte288be162010-05-01 16:48:27 +0200165 1,
166};
167
168static int config_write_sgsn(struct vty *vty)
169{
Harald Welte77289c22010-05-18 14:32:29 +0200170 struct sgsn_ggsn_ctx *gctx;
Harald Welte7f6da482013-03-19 11:00:13 +0100171 struct imsi_acl_entry *acl;
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100172 struct apn_ctx *actx;
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800173 struct ares_addr_node *server;
Harald Welte288be162010-05-01 16:48:27 +0200174
175 vty_out(vty, "sgsn%s", VTY_NEWLINE);
176
Harald Weltee300d002010-06-02 12:41:34 +0200177 vty_out(vty, " gtp local-ip %s%s",
178 inet_ntoa(g_cfg->gtp_listenaddr.sin_addr), VTY_NEWLINE);
179
Harald Welted193cb32010-05-17 22:58:03 +0200180 llist_for_each_entry(gctx, &sgsn_ggsn_ctxts, list) {
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800181 if (gctx->id == UINT32_MAX)
182 continue;
183
Harald Welteff3bde82010-05-19 15:09:09 +0200184 vty_out(vty, " ggsn %u remote-ip %s%s", gctx->id,
Harald Welted193cb32010-05-17 22:58:03 +0200185 inet_ntoa(gctx->remote_addr), VTY_NEWLINE);
Harald Welteff3bde82010-05-19 15:09:09 +0200186 vty_out(vty, " ggsn %u gtp-version %u%s", gctx->id,
Harald Welted193cb32010-05-17 22:58:03 +0200187 gctx->gtp_version, VTY_NEWLINE);
Pau Espin Pedrolfa120102018-07-09 20:37:47 +0200188 if (gctx->echo_interval != -1)
189 vty_out(vty, " ggsn %u echo-interval %"PRId32"%s",
190 gctx->id, gctx->echo_interval, VTY_NEWLINE);
Pau Espin Pedrola83850c2018-07-10 12:43:59 +0200191 else
192 vty_out(vty, " ggsn %u no echo-interval%s",
193 gctx->id, VTY_NEWLINE);
Harald Welte288be162010-05-01 16:48:27 +0200194 }
195
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800196 if (sgsn->cfg.dynamic_lookup)
197 vty_out(vty, " ggsn dynamic%s", VTY_NEWLINE);
198
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800199 for (server = sgsn->ares_servers; server; server = server->next)
200 vty_out(vty, " grx-dns-add %s%s", inet_ntoa(server->addr.addr4), VTY_NEWLINE);
201
Max93408ae2016-06-28 14:10:16 +0200202 if (g_cfg->cipher != GPRS_ALGO_GEA0)
203 vty_out(vty, " encryption %s%s",
204 get_value_string(gprs_cipher_names, g_cfg->cipher),
205 VTY_NEWLINE);
Jacob Erlbeck39f040d2014-12-18 12:46:47 +0100206 if (g_cfg->gsup_server_addr.sin_addr.s_addr)
207 vty_out(vty, " gsup remote-ip %s%s",
208 inet_ntoa(g_cfg->gsup_server_addr.sin_addr), VTY_NEWLINE);
209 if (g_cfg->gsup_server_port)
210 vty_out(vty, " gsup remote-port %d%s",
211 g_cfg->gsup_server_port, VTY_NEWLINE);
Max176b62a2016-07-04 11:09:07 +0200212 vty_out(vty, " auth-policy %s%s",
213 get_value_string(sgsn_auth_pol_strs, g_cfg->auth_policy),
214 VTY_NEWLINE);
Neels Hofmeyr568a7272015-10-12 11:57:38 +0200215
216 vty_out(vty, " gsup oap-id %d%s",
217 (int)g_cfg->oap.client_id, VTY_NEWLINE);
218 if (g_cfg->oap.secret_k_present != 0)
219 vty_out(vty, " gsup oap-k %s%s",
220 osmo_hexdump_nospc(g_cfg->oap.secret_k, sizeof(g_cfg->oap.secret_k)),
221 VTY_NEWLINE);
222 if (g_cfg->oap.secret_opc_present != 0)
223 vty_out(vty, " gsup oap-opc %s%s",
224 osmo_hexdump_nospc(g_cfg->oap.secret_opc, sizeof(g_cfg->oap.secret_opc)),
225 VTY_NEWLINE);
226
Harald Welte7f6da482013-03-19 11:00:13 +0100227 llist_for_each_entry(acl, &g_cfg->imsi_acl, list)
228 vty_out(vty, " imsi-acl add %s%s", acl->imsi, VTY_NEWLINE);
229
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100230 if (llist_empty(&sgsn_apn_ctxts))
231 vty_out(vty, " ! apn * ggsn 0%s", VTY_NEWLINE);
232 llist_for_each_entry(actx, &sgsn_apn_ctxts, list) {
233 if (strlen(actx->imsi_prefix) > 0)
Holger Hans Peter Freytherb7ae0b32015-05-29 15:11:55 +0200234 vty_out(vty, " apn %s imsi-prefix %s ggsn %u%s",
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100235 actx->name, actx->imsi_prefix, actx->ggsn->id,
236 VTY_NEWLINE);
237 else
Holger Hans Peter Freytherb7ae0b32015-05-29 15:11:55 +0200238 vty_out(vty, " apn %s ggsn %u%s", actx->name,
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100239 actx->ggsn->id, VTY_NEWLINE);
240 }
241
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +0200242 if (g_cfg->cdr.filename)
243 vty_out(vty, " cdr filename %s%s", g_cfg->cdr.filename, VTY_NEWLINE);
244 else
245 vty_out(vty, " no cdr filename%s", VTY_NEWLINE);
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +0100246 if (g_cfg->cdr.trap)
247 vty_out(vty, " cdr trap%s", VTY_NEWLINE);
248 else
249 vty_out(vty, " no cdr trap%s", VTY_NEWLINE);
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +0200250 vty_out(vty, " cdr interval %d%s", g_cfg->cdr.interval, VTY_NEWLINE);
251
Harald Welte94508822015-08-15 19:08:21 +0200252 vty_out(vty, " timer t3312 %d%s", g_cfg->timers.T3312, VTY_NEWLINE);
253 vty_out(vty, " timer t3322 %d%s", g_cfg->timers.T3322, VTY_NEWLINE);
254 vty_out(vty, " timer t3350 %d%s", g_cfg->timers.T3350, VTY_NEWLINE);
255 vty_out(vty, " timer t3360 %d%s", g_cfg->timers.T3360, VTY_NEWLINE);
256 vty_out(vty, " timer t3370 %d%s", g_cfg->timers.T3370, VTY_NEWLINE);
257 vty_out(vty, " timer t3313 %d%s", g_cfg->timers.T3313, VTY_NEWLINE);
258 vty_out(vty, " timer t3314 %d%s", g_cfg->timers.T3314, VTY_NEWLINE);
259 vty_out(vty, " timer t3316 %d%s", g_cfg->timers.T3316, VTY_NEWLINE);
260 vty_out(vty, " timer t3385 %d%s", g_cfg->timers.T3385, VTY_NEWLINE);
261 vty_out(vty, " timer t3386 %d%s", g_cfg->timers.T3386, VTY_NEWLINE);
262 vty_out(vty, " timer t3395 %d%s", g_cfg->timers.T3395, VTY_NEWLINE);
263 vty_out(vty, " timer t3397 %d%s", g_cfg->timers.T3397, VTY_NEWLINE);
264
Philippf1f34362016-08-26 17:00:21 +0200265 if (g_cfg->pcomp_rfc1144.active) {
266 vty_out(vty, " compression rfc1144 active slots %d%s",
267 g_cfg->pcomp_rfc1144.s01 + 1, VTY_NEWLINE);
268 } else if (g_cfg->pcomp_rfc1144.passive) {
269 vty_out(vty, " compression rfc1144 passive%s", VTY_NEWLINE);
270 } else
271 vty_out(vty, " no compression rfc1144%s", VTY_NEWLINE);
272
Philipp73f83d52016-09-02 13:38:01 +0200273 if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 1) {
274 vty_out(vty,
275 " compression v42bis active direction sgsn codewords %d strlen %d%s",
276 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
277 VTY_NEWLINE);
278 } else if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 2) {
279 vty_out(vty,
280 " compression v42bis active direction ms codewords %d strlen %d%s",
281 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
282 VTY_NEWLINE);
283 } else if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 3) {
284 vty_out(vty,
285 " compression v42bis active direction both codewords %d strlen %d%s",
286 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
287 VTY_NEWLINE);
288 } else if (g_cfg->dcomp_v42bis.passive) {
289 vty_out(vty, " compression v42bis passive%s", VTY_NEWLINE);
290 } else
291 vty_out(vty, " no compression v42bis%s", VTY_NEWLINE);
292
Neels Hofmeyr2188a772016-05-20 21:59:55 +0200293#ifdef BUILD_IU
Neels Hofmeyra7a39472017-07-05 15:19:52 +0200294 ranap_iu_vty_config_write(vty, " ");
Neels Hofmeyr2188a772016-05-20 21:59:55 +0200295#endif
296
Harald Welte288be162010-05-01 16:48:27 +0200297 return CMD_SUCCESS;
298}
299
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100300#define SGSN_STR "Configure the SGSN\n"
301#define GGSN_STR "Configure the GGSN information\n"
Harald Weltee300d002010-06-02 12:41:34 +0200302
303DEFUN(cfg_sgsn, cfg_sgsn_cmd,
304 "sgsn",
305 SGSN_STR)
Harald Welte288be162010-05-01 16:48:27 +0200306{
307 vty->node = SGSN_NODE;
308 return CMD_SUCCESS;
309}
310
Harald Weltee300d002010-06-02 12:41:34 +0200311DEFUN(cfg_sgsn_bind_addr, cfg_sgsn_bind_addr_cmd,
312 "gtp local-ip A.B.C.D",
313 "GTP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100314 "Set the IP address for the local GTP bind for the Gp interface (towards the GGSNs)."
315 " Note: in case you would like to run the GGSN on the same machine as the SGSN, you can not run"
316 " both on the same IP address, since both sides are specified to use the same GTP port numbers"
317 " (" OSMO_STRINGIFY_VAL(GTP1C_PORT) " and " OSMO_STRINGIFY_VAL(GTP1U_PORT) ")."
318 " For example, you could use 127.0.0.1 for the SGSN and 127.0.0.2 for the GGSN in such"
319 " situations.\n"
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100320 "IPv4 Address\n")
Harald Weltee300d002010-06-02 12:41:34 +0200321{
322 inet_aton(argv[0], &g_cfg->gtp_listenaddr.sin_addr);
323
324 return CMD_SUCCESS;
325}
326
Harald Welted193cb32010-05-17 22:58:03 +0200327DEFUN(cfg_ggsn_remote_ip, cfg_ggsn_remote_ip_cmd,
328 "ggsn <0-255> remote-ip A.B.C.D",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100329 GGSN_STR "GGSN Number\n"
330 "Configure this static GGSN to use the specified remote IP address.\n"
331 "IPv4 Address\n")
Harald Welted193cb32010-05-17 22:58:03 +0200332{
333 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200334 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welte288be162010-05-01 16:48:27 +0200335
Harald Welted193cb32010-05-17 22:58:03 +0200336 inet_aton(argv[1], &ggc->remote_addr);
Harald Welte288be162010-05-01 16:48:27 +0200337
Harald Welted193cb32010-05-17 22:58:03 +0200338 return CMD_SUCCESS;
339}
340
341#if 0
342DEFUN(cfg_ggsn_remote_port, cfg_ggsn_remote_port_cmd,
343 "ggsn <0-255> remote-port <0-65535>",
344 "")
345{
346 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200347 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welted193cb32010-05-17 22:58:03 +0200348 uint16_t port = atoi(argv[1]);
349
350}
351#endif
352
353DEFUN(cfg_ggsn_gtp_version, cfg_ggsn_gtp_version_cmd,
354 "ggsn <0-255> gtp-version (0|1)",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100355 GGSN_STR "GGSN Number\n" "GTP Version\n"
356 "Version 0\n" "Version 1\n")
Harald Welted193cb32010-05-17 22:58:03 +0200357{
358 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200359 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welted193cb32010-05-17 22:58:03 +0200360
361 if (atoi(argv[1]))
362 ggc->gtp_version = 1;
363 else
364 ggc->gtp_version = 0;
365
366 return CMD_SUCCESS;
367}
368
Pau Espin Pedrolfa120102018-07-09 20:37:47 +0200369/* Seee 3GPP TS 29.060 section 7.2.1 */
370DEFUN(cfg_ggsn_echo_interval, cfg_ggsn_echo_interval_cmd,
371 "ggsn <0-255> echo-interval <1-36000>",
372 GGSN_STR "GGSN Number\n"
373 "Send an echo request to this static GGSN every interval.\n"
374 "Interval between echo requests in seconds.\n")
375{
376 uint32_t id = atoi(argv[0]);
377 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
378
379 ggc->echo_interval = atoi(argv[1]);
380
381 if (ggc->echo_interval < 60)
382 vty_out(vty, "%% 3GPP TS 29.060 section states inteval should " \
383 "not be lower than 60 seconds, use this value for " \
384 "testing purposes only!%s", VTY_NEWLINE);
385
Alexander Couzens176a4d22018-09-18 20:07:37 +0200386 sgsn_ggsn_ctx_check_echo_timer(ggc);
Pau Espin Pedrolfa120102018-07-09 20:37:47 +0200387 return CMD_SUCCESS;
388}
389
Pau Espin Pedrola83850c2018-07-10 12:43:59 +0200390DEFUN(cfg_ggsn_no_echo_interval, cfg_ggsn_no_echo_interval_cmd,
391 "ggsn <0-255> no echo-interval",
392 GGSN_STR "GGSN Number\n"
393 NO_STR "Send an echo request to this static GGSN every interval.\n")
394{
395 uint32_t id = atoi(argv[0]);
396 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
397
398 ggc->echo_interval = -1;
Alexander Couzens176a4d22018-09-18 20:07:37 +0200399 sgsn_ggsn_ctx_check_echo_timer(ggc);
Pau Espin Pedrola83850c2018-07-10 12:43:59 +0200400
401 return CMD_SUCCESS;
402}
403
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800404DEFUN(cfg_ggsn_dynamic_lookup, cfg_ggsn_dynamic_lookup_cmd,
405 "ggsn dynamic",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100406 GGSN_STR
407 "Enable dynamic resolving of GGSNs based on DNS resolving the APN name like in a GRX-style setup."
408 " Changing this setting requires a restart.\n")
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800409{
410 sgsn->cfg.dynamic_lookup = 1;
411 return CMD_SUCCESS;
412}
413
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800414DEFUN(cfg_grx_ggsn, cfg_grx_ggsn_cmd,
415 "grx-dns-add A.B.C.D",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100416 "Use the specified IP address for DNS-resolving the AP names to GGSN IP addresses\n"
417 "IPv4 address\n")
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800418{
419 struct ares_addr_node *node = talloc_zero(tall_bsc_ctx, struct ares_addr_node);
420 node->family = AF_INET;
421 inet_aton(argv[0], &node->addr.addr4);
422
423 node->next = sgsn->ares_servers;
424 sgsn->ares_servers = node;
425 return CMD_SUCCESS;
426}
427
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100428#define APN_STR "Configure the information per APN\n"
429#define APN_GW_STR "The APN gateway name optionally prefixed by '*' (wildcard)\n"
430
431static int add_apn_ggsn_mapping(struct vty *vty, const char *apn_str,
432 const char *imsi_prefix, int ggsn_id)
433{
434 struct apn_ctx *actx;
435 struct sgsn_ggsn_ctx *ggsn;
436
437 ggsn = sgsn_ggsn_ctx_by_id(ggsn_id);
438 if (ggsn == NULL) {
439 vty_out(vty, "%% a GGSN with id %d has not been defined%s",
440 ggsn_id, VTY_NEWLINE);
441 return CMD_WARNING;
442 }
443
444 actx = sgsn_apn_ctx_find_alloc(apn_str, imsi_prefix);
445 if (!actx) {
446 vty_out(vty, "%% unable to create APN context for %s/%s%s",
447 apn_str, imsi_prefix, VTY_NEWLINE);
448 return CMD_WARNING;
449 }
450
451 actx->ggsn = ggsn;
452
453 return CMD_SUCCESS;
454}
455
Harald Welted193cb32010-05-17 22:58:03 +0200456DEFUN(cfg_apn_ggsn, cfg_apn_ggsn_cmd,
457 "apn APNAME ggsn <0-255>",
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100458 APN_STR APN_GW_STR
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100459 "Select the GGSN to use for the given APN gateway prefix\n"
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100460 "The GGSN id")
Harald Welted193cb32010-05-17 22:58:03 +0200461{
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100462
463 return add_apn_ggsn_mapping(vty, argv[0], "", atoi(argv[1]));
Harald Welted193cb32010-05-17 22:58:03 +0200464}
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100465
466DEFUN(cfg_apn_imsi_ggsn, cfg_apn_imsi_ggsn_cmd,
467 "apn APNAME imsi-prefix IMSIPRE ggsn <0-255>",
468 APN_STR APN_GW_STR
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100469 "Select the GGSN to use for the given APN gateway prefix if and only if the IMSI matches the"
470 " given prefix.\n"
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100471 "An IMSI prefix\n"
472 "Select the GGSN to use when APN gateway and IMSI prefix match\n"
473 "The GGSN id")
474{
475
476 return add_apn_ggsn_mapping(vty, argv[0], argv[1], atoi(argv[2]));
477}
Harald Welted193cb32010-05-17 22:58:03 +0200478
479const struct value_string gprs_mm_st_strs[] = {
480 { GMM_DEREGISTERED, "DEREGISTERED" },
481 { GMM_COMMON_PROC_INIT, "COMMON PROCEDURE (INIT)" },
482 { GMM_REGISTERED_NORMAL, "REGISTERED (NORMAL)" },
Harald Weltebffeff82010-06-09 15:50:45 +0200483 { GMM_REGISTERED_SUSPENDED, "REGISTERED (SUSPENDED)" },
Harald Welted193cb32010-05-17 22:58:03 +0200484 { GMM_DEREGISTERED_INIT, "DEREGISTERED (INIT)" },
485 { 0, NULL }
486};
487
Maxc005db72017-10-27 18:43:29 +0200488char *sgsn_gtp_ntoa(struct ul16_t *ul)
Harald Welte471ac7d2016-12-15 19:48:58 +0100489{
Max8492c202017-12-05 17:28:15 +0100490 struct in_addr ia;
491
492 if (gsna2in_addr(&ia, ul) != 0)
Harald Welte471ac7d2016-12-15 19:48:58 +0100493 return "UNKNOWN";
Max8492c202017-12-05 17:28:15 +0100494
495 return inet_ntoa(ia);
Harald Welte471ac7d2016-12-15 19:48:58 +0100496}
497
Harald Welted193cb32010-05-17 22:58:03 +0200498static void vty_dump_pdp(struct vty *vty, const char *pfx,
499 struct sgsn_pdp_ctx *pdp)
500{
Jacob Erlbeck99985b52014-10-13 10:32:00 +0200501 const char *imsi = pdp->mm ? pdp->mm->imsi : "(detaching)";
Harald Welte471ac7d2016-12-15 19:48:58 +0100502 vty_out(vty, "%sPDP Context IMSI: %s, SAPI: %u, NSAPI: %u, TI: %u%s",
503 pfx, imsi, pdp->sapi, pdp->nsapi, pdp->ti, VTY_NEWLINE);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200504 if (pdp->lib) {
Max7933d962017-10-19 16:52:30 +0200505 char apnbuf[APN_MAXLEN + 1];
Harald Weltedfbd2c82017-08-13 00:56:45 +0200506 vty_out(vty, "%s APN: %s%s", pfx,
Max7933d962017-10-19 16:52:30 +0200507 osmo_apn_to_str(apnbuf, pdp->lib->apn_use.v, pdp->lib->apn_use.l),
Harald Weltedfbd2c82017-08-13 00:56:45 +0200508 VTY_NEWLINE);
509 vty_out(vty, "%s PDP Address: %s%s", pfx,
510 gprs_pdpaddr2str(pdp->lib->eua.v, pdp->lib->eua.l),
511 VTY_NEWLINE);
Maxb24af2b2017-12-05 17:54:42 +0100512 vty_out(vty, "%s GTPv%d Local Control(%s / TEIC: 0x%08x) ", pfx, pdp->lib->version,
Maxc005db72017-10-27 18:43:29 +0200513 sgsn_gtp_ntoa(&pdp->lib->gsnlc), pdp->lib->teic_own);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200514 vty_out(vty, "Data(%s / TEID: 0x%08x)%s",
Maxc005db72017-10-27 18:43:29 +0200515 sgsn_gtp_ntoa(&pdp->lib->gsnlu), pdp->lib->teid_own, VTY_NEWLINE);
Maxb24af2b2017-12-05 17:54:42 +0100516 vty_out(vty, "%s GTPv%d Remote Control(%s / TEIC: 0x%08x) ", pfx, pdp->lib->version,
Maxc005db72017-10-27 18:43:29 +0200517 sgsn_gtp_ntoa(&pdp->lib->gsnrc), pdp->lib->teic_gn);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200518 vty_out(vty, "Data(%s / TEID: 0x%08x)%s",
Maxc005db72017-10-27 18:43:29 +0200519 sgsn_gtp_ntoa(&pdp->lib->gsnru), pdp->lib->teid_gn, VTY_NEWLINE);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200520 }
Harald Welte471ac7d2016-12-15 19:48:58 +0100521
Harald Welteefbdee92010-06-10 00:20:12 +0200522 vty_out_rate_ctr_group(vty, " ", pdp->ctrg);
Harald Welted193cb32010-05-17 22:58:03 +0200523}
524
525static void vty_dump_mmctx(struct vty *vty, const char *pfx,
526 struct sgsn_mm_ctx *mm, int pdp)
527{
528 vty_out(vty, "%sMM Context for IMSI %s, IMEI %s, P-TMSI %08x%s",
529 pfx, mm->imsi, mm->imei, mm->p_tmsi, VTY_NEWLINE);
Holger Hans Peter Freyther8ee13e22015-05-18 10:00:03 +0200530 vty_out(vty, "%s MSISDN: %s, TLLI: %08x%s HLR: %s",
Harald Weltef97ee042015-12-25 19:12:21 +0100531 pfx, mm->msisdn, mm->gb.tlli, mm->hlr, VTY_NEWLINE);
Neels Hofmeyr10719b72018-02-21 00:39:36 +0100532 vty_out(vty, "%s MM State: %s, Routeing Area: %s, Cell ID: %u%s",
533 pfx, get_value_string(gprs_mm_st_strs, mm->gmm_state),
534 osmo_rai_name(&mm->ra), mm->gb.cell_id, VTY_NEWLINE);
Harald Welted193cb32010-05-17 22:58:03 +0200535
Harald Welte8acd88f2010-05-18 10:57:45 +0200536 vty_out_rate_ctr_group(vty, " ", mm->ctrg);
537
Harald Welted193cb32010-05-17 22:58:03 +0200538 if (pdp) {
539 struct sgsn_pdp_ctx *pdp;
540
541 llist_for_each_entry(pdp, &mm->pdp_list, list)
542 vty_dump_pdp(vty, " ", pdp);
543 }
544}
545
546DEFUN(show_sgsn, show_sgsn_cmd, "show sgsn",
547 SHOW_STR "Display information about the SGSN")
548{
Jacob Erlbeck80547992014-12-19 19:19:46 +0100549 if (sgsn->gsup_client) {
550 struct ipa_client_conn *link = sgsn->gsup_client->link;
551 vty_out(vty,
552 " Remote authorization: %sconnected to %s:%d via GSUP%s",
553 sgsn->gsup_client->is_connected ? "" : "not ",
554 link->addr, link->port,
555 VTY_NEWLINE);
556 }
Maxbaabc682017-10-20 13:39:57 +0200557 if (sgsn->gsn)
558 vty_out(vty, " GSN: signalling %s, user traffic %s%s",
559 inet_ntoa(sgsn->gsn->gsnc), inet_ntoa(sgsn->gsn->gsnu), VTY_NEWLINE);
560
Harald Welted193cb32010-05-17 22:58:03 +0200561 /* FIXME: statistics */
562 return CMD_SUCCESS;
563}
564
565#define MMCTX_STR "MM Context\n"
566#define INCLUDE_PDP_STR "Include PDP Context Information\n"
567
568#if 0
569DEFUN(show_mmctx_tlli, show_mmctx_tlli_cmd,
570 "show mm-context tlli HEX [pdp]",
571 SHOW_STR MMCTX_STR "Identify by TLLI\n" "TLLI\n" INCLUDE_PDP_STR)
572{
573 uint32_t tlli;
574 struct sgsn_mm_ctx *mm;
575
576 tlli = strtoul(argv[0], NULL, 16);
577 mm = sgsn_mm_ctx_by_tlli(tlli);
578 if (!mm) {
579 vty_out(vty, "No MM context for TLLI %08x%s",
580 tlli, VTY_NEWLINE);
581 return CMD_WARNING;
582 }
583 vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
584 return CMD_SUCCESS;
585}
586#endif
587
588DEFUN(swow_mmctx_imsi, show_mmctx_imsi_cmd,
589 "show mm-context imsi IMSI [pdp]",
590 SHOW_STR MMCTX_STR "Identify by IMSI\n" "IMSI of the MM Context\n"
591 INCLUDE_PDP_STR)
592{
593 struct sgsn_mm_ctx *mm;
594
595 mm = sgsn_mm_ctx_by_imsi(argv[0]);
596 if (!mm) {
597 vty_out(vty, "No MM context for IMSI %s%s",
598 argv[0], VTY_NEWLINE);
599 return CMD_WARNING;
600 }
601 vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
602 return CMD_SUCCESS;
603}
604
605DEFUN(swow_mmctx_all, show_mmctx_all_cmd,
606 "show mm-context all [pdp]",
607 SHOW_STR MMCTX_STR "All MM Contexts\n" INCLUDE_PDP_STR)
608{
609 struct sgsn_mm_ctx *mm;
610
611 llist_for_each_entry(mm, &sgsn_mm_ctxts, list)
612 vty_dump_mmctx(vty, "", mm, argv[0] ? 1 : 0);
613
614 return CMD_SUCCESS;
615}
616
Harald Welted193cb32010-05-17 22:58:03 +0200617DEFUN(show_pdpctx_all, show_pdpctx_all_cmd,
618 "show pdp-context all",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100619 SHOW_STR "Display information on PDP Context\n" "Show everything\n")
Harald Welted193cb32010-05-17 22:58:03 +0200620{
621 struct sgsn_pdp_ctx *pdp;
622
623 llist_for_each_entry(pdp, &sgsn_pdp_ctxts, g_list)
624 vty_dump_pdp(vty, "", pdp);
625
626 return CMD_SUCCESS;
627}
Harald Welte288be162010-05-01 16:48:27 +0200628
Harald Welte7f6da482013-03-19 11:00:13 +0100629
630DEFUN(imsi_acl, cfg_imsi_acl_cmd,
631 "imsi-acl (add|del) IMSI",
632 "Access Control List of foreign IMSIs\n"
633 "Add IMSI to ACL\n"
634 "Remove IMSI from ACL\n"
635 "IMSI of subscriber\n")
636{
Philipp Maier6ee49d82017-02-28 16:53:07 +0100637 char imsi_sanitized[GSM23003_IMSI_MAX_DIGITS+1];
Harald Welte7f6da482013-03-19 11:00:13 +0100638 const char *op = argv[0];
Philipp Maier6ee49d82017-02-28 16:53:07 +0100639 const char *imsi = imsi_sanitized;
Harald Welte7f6da482013-03-19 11:00:13 +0100640 int rc;
641
Philipp Maier6ee49d82017-02-28 16:53:07 +0100642 /* Sanitize IMSI */
643 if (strlen(argv[1]) > GSM23003_IMSI_MAX_DIGITS) {
644 vty_out(vty, "%% IMSI (%s) too long -- ignored!%s",
645 argv[1], VTY_NEWLINE);
646 return CMD_WARNING;
647 }
648 memset(imsi_sanitized, '0', sizeof(imsi_sanitized));
649 strcpy(imsi_sanitized+GSM23003_IMSI_MAX_DIGITS-strlen(argv[1]),argv[1]);
650
Harald Welte7f6da482013-03-19 11:00:13 +0100651 if (!strcmp(op, "add"))
Jacob Erlbeck3b5d4072014-10-24 15:11:03 +0200652 rc = sgsn_acl_add(imsi, g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +0100653 else
Jacob Erlbeck3b5d4072014-10-24 15:11:03 +0200654 rc = sgsn_acl_del(imsi, g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +0100655
656 if (rc < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100657 vty_out(vty, "%% unable to %s ACL%s", op, VTY_NEWLINE);
Harald Welte7f6da482013-03-19 11:00:13 +0100658 return CMD_WARNING;
659 }
660
661 return CMD_SUCCESS;
662}
663
Max93408ae2016-06-28 14:10:16 +0200664DEFUN(cfg_encrypt, cfg_encrypt_cmd,
665 "encryption (GEA0|GEA1|GEA2|GEA3|GEA4)",
666 "Set encryption algorithm for SGSN\n"
667 "Use GEA0 (no encryption)\n"
668 "Use GEA1\nUse GEA2\nUse GEA3\nUse GEA4\n")
669{
Max93408ae2016-06-28 14:10:16 +0200670 enum gprs_ciph_algo c = get_string_value(gprs_cipher_names, argv[0]);
Max086067f2017-05-02 13:03:28 +0200671 if (c != GPRS_ALGO_GEA0) {
672 if (!gprs_cipher_supported(c)) {
673 vty_out(vty, "%% cipher %s is unsupported in current version%s", argv[0], VTY_NEWLINE);
674 return CMD_WARNING;
675 }
676
677 if (!g_cfg->require_authentication) {
678 vty_out(vty, "%% unable to use encryption %s without authentication: please adjust auth-policy%s",
679 argv[0], VTY_NEWLINE);
680 return CMD_WARNING;
681 }
Max93408ae2016-06-28 14:10:16 +0200682 }
683
684 g_cfg->cipher = c;
685
686 return CMD_SUCCESS;
687}
688
Harald Welte3dfb5492013-03-19 11:48:54 +0100689DEFUN(cfg_auth_policy, cfg_auth_policy_cmd,
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100690 "auth-policy (accept-all|closed|acl-only|remote)",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100691 "Configure the Authorization policy of the SGSN. This setting determines which subscribers are"
692 " permitted to register to the network.\n"
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100693 "Accept all IMSIs (DANGEROUS)\n"
694 "Accept only home network subscribers or those in the ACL\n"
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100695 "Accept only subscribers in the ACL\n"
696 "Use remote subscription data only (HLR)\n")
Harald Welte3dfb5492013-03-19 11:48:54 +0100697{
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100698 int val = get_string_value(sgsn_auth_pol_strs, argv[0]);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100699 OSMO_ASSERT(val >= SGSN_AUTH_POLICY_OPEN && val <= SGSN_AUTH_POLICY_REMOTE);
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100700 g_cfg->auth_policy = val;
Jacob Erlbeck9d4f46c2014-12-17 13:20:08 +0100701 g_cfg->require_authentication = (val == SGSN_AUTH_POLICY_REMOTE);
Jacob Erlbeck771573c2014-12-19 18:08:48 +0100702 g_cfg->require_update_location = (val == SGSN_AUTH_POLICY_REMOTE);
Harald Welte3dfb5492013-03-19 11:48:54 +0100703
704 return CMD_SUCCESS;
705}
706
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100707/* Subscriber */
Neels Hofmeyr396f2e62017-09-04 15:13:25 +0200708#include <osmocom/sgsn/gprs_subscriber.h>
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100709
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100710static void subscr_dump_full_vty(struct vty *vty, struct gprs_subscr *gsub, int pending)
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100711{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100712#if 0
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100713 char expire_time[200];
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100714#endif
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100715 struct gsm_auth_tuple *at;
716 int at_idx;
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100717 struct sgsn_subscriber_pdp_data *pdp;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100718
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100719 vty_out(vty, " Authorized: %d%s",
720 gsub->authorized, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100721 vty_out(vty, " LAC: %d/0x%x%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100722 gsub->lac, gsub->lac, VTY_NEWLINE);
723 vty_out(vty, " IMSI: %s%s", gsub->imsi, VTY_NEWLINE);
724 if (gsub->tmsi != GSM_RESERVED_TMSI)
725 vty_out(vty, " TMSI: %08X%s", gsub->tmsi,
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100726 VTY_NEWLINE);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100727 if (gsub->sgsn_data->msisdn_len > 0)
Holger Hans Peter Freytherf7b38262015-04-23 16:58:33 -0400728 vty_out(vty, " MSISDN (BCD): %s%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100729 osmo_hexdump(gsub->sgsn_data->msisdn,
730 gsub->sgsn_data->msisdn_len),
Holger Hans Peter Freytherf7b38262015-04-23 16:58:33 -0400731 VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100732
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100733 if (strlen(gsub->imei) > 0)
734 vty_out(vty, " IMEI: %s%s", gsub->imei, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100735
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100736 for (at_idx = 0; at_idx < ARRAY_SIZE(gsub->sgsn_data->auth_triplets);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100737 at_idx++) {
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100738 at = &gsub->sgsn_data->auth_triplets[at_idx];
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100739 if (at->key_seq == GSM_KEY_SEQ_INVAL)
740 continue;
741
742 vty_out(vty, " A3A8 tuple (used %d times): ",
743 at->use_count);
Harald Welte89837d42016-05-06 23:28:11 +0200744 vty_out(vty, " CKSN: %d, ",
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100745 at->key_seq);
Harald Welte89837d42016-05-06 23:28:11 +0200746 if (at->vec.auth_types & OSMO_AUTH_TYPE_GSM) {
747 vty_out(vty, "RAND: %s, ",
748 osmo_hexdump(at->vec.rand,
749 sizeof(at->vec.rand)));
750 vty_out(vty, "SRES: %s, ",
751 osmo_hexdump(at->vec.sres,
752 sizeof(at->vec.sres)));
753 vty_out(vty, "Kc: %s%s",
754 osmo_hexdump(at->vec.kc,
755 sizeof(at->vec.kc)), VTY_NEWLINE);
756 }
757 if (at->vec.auth_types & OSMO_AUTH_TYPE_UMTS) {
758 vty_out(vty, " AUTN: %s, ",
759 osmo_hexdump(at->vec.autn,
760 sizeof(at->vec.autn)));
761 vty_out(vty, "RES: %s, ",
762 osmo_hexdump(at->vec.res, at->vec.res_len));
763 vty_out(vty, "IK: %s, ",
764 osmo_hexdump(at->vec.ik, sizeof(at->vec.ik)));
765 vty_out(vty, "CK: %s, ",
766 osmo_hexdump(at->vec.ck, sizeof(at->vec.ck)));
767 }
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100768 }
769
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100770 llist_for_each_entry(pdp, &gsub->sgsn_data->pdp_list, list) {
Holger Hans Peter Freytherd05e0692015-04-23 16:59:04 -0400771 vty_out(vty, " PDP info: Id: %d, Type: 0x%04x, APN: '%s' QoS: %s%s",
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100772 pdp->context_id, pdp->pdp_type, pdp->apn_str,
Holger Hans Peter Freytherd05e0692015-04-23 16:59:04 -0400773 osmo_hexdump(pdp->qos_subscribed, pdp->qos_subscribed_len),
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100774 VTY_NEWLINE);
775 }
776
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100777#if 0
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100778 /* print the expiration time of a subscriber */
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100779 if (gsub->expire_lu) {
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100780 strftime(expire_time, sizeof(expire_time),
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100781 "%a, %d %b %Y %T %z", localtime(&gsub->expire_lu));
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100782 expire_time[sizeof(expire_time) - 1] = '\0';
783 vty_out(vty, " Expiration Time: %s%s", expire_time, VTY_NEWLINE);
784 }
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100785#endif
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100786
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100787 if (gsub->flags)
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100788 vty_out(vty, " Flags: %s%s%s%s%s%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100789 gsub->flags & GPRS_SUBSCRIBER_FIRST_CONTACT ?
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100790 "FIRST_CONTACT " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100791 gsub->flags & GPRS_SUBSCRIBER_CANCELLED ?
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100792 "CANCELLED " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100793 gsub->flags & GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING ?
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100794 "UPDATE_LOCATION_PENDING " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100795 gsub->flags & GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING ?
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100796 "AUTH_INFO_PENDING " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100797 gsub->flags & GPRS_SUBSCRIBER_ENABLE_PURGE ?
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100798 "ENABLE_PURGE " : "",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100799 VTY_NEWLINE);
800
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100801 vty_out(vty, " Use count: %u%s", gsub->use_count, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100802}
803
Neels Hofmeyr1a9414b2018-09-24 18:14:29 +0200804#define RESET_SGSN_STATE_STR \
805 "Remove all known subscribers, MM contexts and flush BSSGP queues." \
806 " Useful only when running tests against the SGSN\n"
807
Alexander Couzensc503f0a2018-08-07 17:50:04 +0200808DEFUN_HIDDEN(reset_sgsn_state,
809 reset_sgsn_state_cmd,
810 "reset sgsn state",
Neels Hofmeyr1a9414b2018-09-24 18:14:29 +0200811 RESET_SGSN_STATE_STR RESET_SGSN_STATE_STR RESET_SGSN_STATE_STR)
Alexander Couzensc503f0a2018-08-07 17:50:04 +0200812{
813 struct gprs_subscr *subscr, *tmp_subscr;
814 struct sgsn_mm_ctx *mm, *tmp_mm;
815
816 llist_for_each_entry_safe(mm, tmp_mm, &sgsn_mm_ctxts, list)
817 {
818 gsm0408_gprs_access_cancelled(mm, SGSN_ERROR_CAUSE_NONE);
819 }
820 vty_out(vty, "Cancelled MM Ctx. %s", VTY_NEWLINE);
821
822 llist_for_each_entry_safe(subscr, tmp_subscr, gprs_subscribers, entry) {
823 gprs_subscr_get(subscr);
824 gprs_subscr_cancel(subscr);
825 gprs_subscr_put(subscr);
826 }
827 vty_out(vty, "Removed all gprs subscribers.%s", VTY_NEWLINE);
828
829 bssgp_flush_all_queues();
830 vty_out(vty, "Flushed all BSSGPs queues.%s", VTY_NEWLINE);
831
Alexander Couzens35c34942018-09-17 04:39:14 +0200832 gtp_clear_queues(sgsn->gsn);
Alexander Couzensa66f0f22018-09-18 16:09:18 +0200833 vty_out(vty, "Flushed rx & tx queus towards the GGSN.%s", VTY_NEWLINE);
Alexander Couzens35c34942018-09-17 04:39:14 +0200834
Alexander Couzensc503f0a2018-08-07 17:50:04 +0200835 /* remove all queues to bssgp */
836 return CMD_SUCCESS;
837}
838
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100839DEFUN(show_subscr_cache,
840 show_subscr_cache_cmd,
841 "show subscriber cache",
842 SHOW_STR "Show information about subscribers\n"
843 "Display contents of subscriber cache\n")
844{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100845 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100846
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100847 llist_for_each_entry(subscr, gprs_subscribers, entry) {
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100848 vty_out(vty, " Subscriber:%s", VTY_NEWLINE);
849 subscr_dump_full_vty(vty, subscr, 0);
850 }
851
852 return CMD_SUCCESS;
853}
854
855#define UPDATE_SUBSCR_STR "update-subscriber imsi IMSI "
856#define UPDATE_SUBSCR_HELP "Update subscriber list\n" \
857 "Use the IMSI to select the subscriber\n" \
858 "The IMSI\n"
859
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100860#define UPDATE_SUBSCR_INSERT_HELP "Insert data into the subscriber record\n"
861
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100862DEFUN(update_subscr_insert_auth_triplet, update_subscr_insert_auth_triplet_cmd,
863 UPDATE_SUBSCR_STR "insert auth-triplet <1-5> sres SRES rand RAND kc KC",
864 UPDATE_SUBSCR_HELP
865 UPDATE_SUBSCR_INSERT_HELP
866 "Update authentication triplet\n"
867 "Triplet index\n"
868 "Set SRES value\nSRES value (4 byte) in hex\n"
869 "Set RAND value\nRAND value (16 byte) in hex\n"
870 "Set Kc value\nKc value (8 byte) in hex\n")
871{
872 const char *imsi = argv[0];
873 const int cksn = atoi(argv[1]) - 1;
874 const char *sres_str = argv[2];
875 const char *rand_str = argv[3];
876 const char *kc_str = argv[4];
877 struct gsm_auth_tuple at = {0,};
878
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100879 struct gprs_subscr *subscr;
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100880
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100881 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100882 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100883 vty_out(vty, "%% unable get subscriber record for %s%s",
884 imsi, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100885 return CMD_WARNING;
886 }
887
888 OSMO_ASSERT(subscr->sgsn_data);
889
Harald Welte121e9a42016-04-20 13:13:19 +0200890 if (osmo_hexparse(sres_str, &at.vec.sres[0], sizeof(at.vec.sres)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100891 vty_out(vty, "%% invalid SRES value '%s'%s",
892 sres_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100893 goto failed;
894 }
Harald Welte121e9a42016-04-20 13:13:19 +0200895 if (osmo_hexparse(rand_str, &at.vec.rand[0], sizeof(at.vec.rand)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100896 vty_out(vty, "%% invalid RAND value '%s'%s",
897 rand_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100898 goto failed;
899 }
Harald Welte121e9a42016-04-20 13:13:19 +0200900 if (osmo_hexparse(kc_str, &at.vec.kc[0], sizeof(at.vec.kc)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100901 vty_out(vty, "%% invalid Kc value '%s'%s",
902 kc_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100903 goto failed;
904 }
905 at.key_seq = cksn;
906
907 subscr->sgsn_data->auth_triplets[cksn] = at;
908 subscr->sgsn_data->auth_triplets_updated = 1;
909
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100910 gprs_subscr_put(subscr);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100911
912 return CMD_SUCCESS;
913
914failed:
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100915 gprs_subscr_put(subscr);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100916 return CMD_SUCCESS;
917}
918
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100919DEFUN(update_subscr_cancel, update_subscr_cancel_cmd,
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100920 UPDATE_SUBSCR_STR "cancel (update-procedure|subscription-withdraw)",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100921 UPDATE_SUBSCR_HELP
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100922 "Cancel (remove) subscriber record\n"
923 "The MS moved to another SGSN\n"
924 "The subscription is no longer valid\n")
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100925{
926 const char *imsi = argv[0];
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100927 const char *cancel_type = argv[1];
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100928
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100929 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100930
931 subscr = gprs_subscr_get_by_imsi(imsi);
932 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100933 vty_out(vty, "%% no subscriber record for %s%s",
934 imsi, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100935 return CMD_WARNING;
936 }
937
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100938 if (strcmp(cancel_type, "update-procedure") == 0)
939 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
940 else
941 subscr->sgsn_data->error_cause = GMM_CAUSE_IMPL_DETACHED;
942
Jacob Erlbeck37139e52015-01-23 13:52:55 +0100943 gprs_subscr_cancel(subscr);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100944 gprs_subscr_put(subscr);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100945
946 return CMD_SUCCESS;
947}
948
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100949DEFUN(update_subscr_create, update_subscr_create_cmd,
950 UPDATE_SUBSCR_STR "create",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100951 UPDATE_SUBSCR_HELP
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100952 "Create a subscriber entry\n")
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100953{
954 const char *imsi = argv[0];
955
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100956 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100957
958 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100959 if (subscr) {
960 vty_out(vty, "%% subscriber record already exists for %s%s",
961 imsi, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100962 return CMD_WARNING;
963 }
964
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100965 subscr = gprs_subscr_get_or_create(imsi);
966 subscr->keep_in_ram = 1;
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100967 gprs_subscr_put(subscr);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100968
969 return CMD_SUCCESS;
970}
971
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100972DEFUN(update_subscr_destroy, update_subscr_destroy_cmd,
973 UPDATE_SUBSCR_STR "destroy",
974 UPDATE_SUBSCR_HELP
975 "Destroy a subscriber entry\n")
976{
977 const char *imsi = argv[0];
978
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100979 struct gprs_subscr *subscr;
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100980
981 subscr = gprs_subscr_get_by_imsi(imsi);
982 if (!subscr) {
983 vty_out(vty, "%% subscriber record does not exist for %s%s",
984 imsi, VTY_NEWLINE);
985 return CMD_WARNING;
986 }
987
988 subscr->keep_in_ram = 0;
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100989 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100990 gprs_subscr_cancel(subscr);
991 if (subscr->use_count > 1)
992 vty_out(vty, "%% subscriber is still in use%s",
993 VTY_NEWLINE);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100994 gprs_subscr_put(subscr);
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100995
996 return CMD_SUCCESS;
997}
998
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100999#define UL_ERR_STR "system-failure|data-missing|unexpected-data-value|" \
1000 "unknown-subscriber|roaming-not-allowed"
1001
1002#define UL_ERR_HELP \
1003 "Force error code SystemFailure\n" \
1004 "Force error code DataMissing\n" \
1005 "Force error code UnexpectedDataValue\n" \
1006 "Force error code UnknownSubscriber\n" \
1007 "Force error code RoamingNotAllowed\n"
1008
1009DEFUN(update_subscr_update_location_result, update_subscr_update_location_result_cmd,
1010 UPDATE_SUBSCR_STR "update-location-result (ok|" UL_ERR_STR ")",
1011 UPDATE_SUBSCR_HELP
1012 "Complete the update location procedure\n"
1013 "The update location request succeeded\n"
1014 UL_ERR_HELP)
1015{
1016 const char *imsi = argv[0];
1017 const char *ret_code_str = argv[1];
1018
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001019 struct gprs_subscr *subscr;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001020
Jacob Erlbeckd6267d12015-01-19 11:10:04 +01001021 const struct value_string cause_mapping[] = {
1022 { GMM_CAUSE_NET_FAIL, "system-failure" },
1023 { GMM_CAUSE_INV_MAND_INFO, "data-missing" },
1024 { GMM_CAUSE_PROTO_ERR_UNSPEC, "unexpected-data-value" },
1025 { GMM_CAUSE_IMSI_UNKNOWN, "unknown-subscriber" },
1026 { GMM_CAUSE_GPRS_NOTALLOWED, "roaming-not-allowed" },
1027 { 0, NULL }
1028 };
1029
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001030 subscr = gprs_subscr_get_by_imsi(imsi);
1031 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +01001032 vty_out(vty, "%% unable to get subscriber record for %s%s",
1033 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001034 return CMD_WARNING;
1035 }
Jacob Erlbeckd6267d12015-01-19 11:10:04 +01001036
1037 if (strcmp(ret_code_str, "ok") == 0) {
1038 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001039 subscr->authorized = 1;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +01001040 } else {
1041 subscr->sgsn_data->error_cause =
1042 get_string_value(cause_mapping, ret_code_str);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001043 subscr->authorized = 0;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +01001044 }
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001045
1046 gprs_subscr_update(subscr);
1047
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001048 gprs_subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001049
1050 return CMD_SUCCESS;
1051}
1052
1053DEFUN(update_subscr_update_auth_info, update_subscr_update_auth_info_cmd,
1054 UPDATE_SUBSCR_STR "update-auth-info",
1055 UPDATE_SUBSCR_HELP
1056 "Complete the send authentication info procedure\n")
1057{
1058 const char *imsi = argv[0];
1059
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001060 struct gprs_subscr *subscr;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001061
1062 subscr = gprs_subscr_get_by_imsi(imsi);
1063 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +01001064 vty_out(vty, "%% unable to get subscriber record for %s%s",
1065 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001066 return CMD_WARNING;
1067 }
1068
1069 gprs_subscr_update_auth_info(subscr);
1070
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001071 gprs_subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001072
1073 return CMD_SUCCESS;
1074}
1075
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001076DEFUN(cfg_gsup_remote_ip, cfg_gsup_remote_ip_cmd,
1077 "gsup remote-ip A.B.C.D",
1078 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001079 "Set the IP address of the remote GSUP server (e.g. OsmoHLR)."
1080 " This setting only applies if 'auth-policy remote' is used.\n"
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001081 "IPv4 Address\n")
1082{
1083 inet_aton(argv[0], &g_cfg->gsup_server_addr.sin_addr);
1084
1085 return CMD_SUCCESS;
1086}
1087
1088DEFUN(cfg_gsup_remote_port, cfg_gsup_remote_port_cmd,
1089 "gsup remote-port <0-65535>",
1090 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001091 "Set the TCP port of the remote GSUP server, see also 'gsup remote-ip'\n"
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001092 "Remote TCP port\n")
1093{
1094 g_cfg->gsup_server_port = atoi(argv[0]);
1095
1096 return CMD_SUCCESS;
1097}
1098
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001099DEFUN(cfg_gsup_oap_id, cfg_gsup_oap_id_cmd,
1100 "gsup oap-id <0-65535>",
1101 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001102 "Set the OAP client ID for authentication on the GSUP protocol."
1103 " This setting only applies if 'auth-policy remote' is used.\n"
1104 "OAP client ID (0 == disabled)\n")
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001105{
1106 /* VTY ensures range */
1107 g_cfg->oap.client_id = (uint16_t)atoi(argv[0]);
1108 return CMD_SUCCESS;
1109}
1110
1111DEFUN(cfg_gsup_oap_k, cfg_gsup_oap_k_cmd,
1112 "gsup oap-k K",
1113 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001114 "Set the OAP shared secret key K for authentication on the GSUP protocol."
1115 " This setting only applies if auth-policy remote is used.\n"
1116 "K value (16 byte) hex\n")
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001117{
1118 const char *k = argv[0];
1119
1120 g_cfg->oap.secret_k_present = 0;
1121
1122 if ((!k) || (strlen(k) == 0))
1123 goto disable;
1124
1125 int k_len = osmo_hexparse(k,
1126 g_cfg->oap.secret_k,
1127 sizeof(g_cfg->oap.secret_k));
1128 if (k_len != 16) {
1129 vty_out(vty, "%% need exactly 16 octets for oap-k, got %d.%s",
1130 k_len, VTY_NEWLINE);
1131 goto disable;
1132 }
1133
1134 g_cfg->oap.secret_k_present = 1;
1135 return CMD_SUCCESS;
1136
1137disable:
1138 if (g_cfg->oap.client_id > 0) {
1139 vty_out(vty, "%% OAP client ID set, but invalid oap-k value disables OAP.%s",
1140 VTY_NEWLINE);
1141 return CMD_WARNING;
1142 }
1143 return CMD_SUCCESS;
1144}
1145
1146DEFUN(cfg_gsup_oap_opc, cfg_gsup_oap_opc_cmd,
1147 "gsup oap-opc OPC",
1148 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001149 "Set the OAP shared secret OPC for authentication on the GSUP protocol."
1150 " This setting only applies if auth-policy remote is used.\n"
1151 "OPC value (16 byte) hex\n")
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001152{
1153 const char *opc = argv[0];
1154
1155 g_cfg->oap.secret_opc_present = 0;
1156
1157 if ((!opc) || (strlen(opc) == 0))
1158 goto disable;
1159
1160 int opc_len = osmo_hexparse(opc,
1161 g_cfg->oap.secret_opc,
1162 sizeof(g_cfg->oap.secret_opc));
1163 if (opc_len != 16) {
1164 vty_out(vty, "%% need exactly 16 octets for oap-opc, got %d.%s",
1165 opc_len, VTY_NEWLINE);
1166 goto disable;
1167 }
1168
1169 g_cfg->oap.secret_opc_present = 1;
1170 return CMD_SUCCESS;
1171
1172disable:
1173 if (g_cfg->oap.client_id > 0) {
1174 vty_out(vty, "%% OAP client ID set, but invalid oap-opc value disables OAP.%s",
1175 VTY_NEWLINE);
1176 return CMD_WARNING;
1177 }
1178 return CMD_SUCCESS;
1179}
1180
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001181DEFUN(cfg_apn_name, cfg_apn_name_cmd,
1182 "access-point-name NAME",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001183 "Globally allow the given APN name for all subscribers.\n"
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001184 "Add this NAME to the list\n")
1185{
1186 return add_apn_ggsn_mapping(vty, argv[0], "", 0);
1187}
1188
1189DEFUN(cfg_no_apn_name, cfg_no_apn_name_cmd,
1190 "no access-point-name NAME",
1191 NO_STR "Configure a global list of allowed APNs\n"
1192 "Remove entry with NAME\n")
1193{
1194 struct apn_ctx *apn_ctx = sgsn_apn_ctx_by_name(argv[0], "");
1195 if (!apn_ctx)
1196 return CMD_SUCCESS;
1197
1198 sgsn_apn_ctx_free(apn_ctx);
1199 return CMD_SUCCESS;
1200}
1201
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001202DEFUN(cfg_cdr_filename, cfg_cdr_filename_cmd,
1203 "cdr filename NAME",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001204 "CDR\n"
1205 "Set the file name for the call-data-record file, logging the data usage of each subscriber.\n"
1206 "filename\n")
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001207{
1208 talloc_free(g_cfg->cdr.filename);
1209 g_cfg->cdr.filename = talloc_strdup(tall_vty_ctx, argv[0]);
1210 return CMD_SUCCESS;
1211}
1212
1213DEFUN(cfg_no_cdr_filename, cfg_no_cdr_filename_cmd,
1214 "no cdr filename",
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +01001215 NO_STR "CDR\nDisable saving CDR to file\n")
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001216{
1217 talloc_free(g_cfg->cdr.filename);
1218 g_cfg->cdr.filename = NULL;
1219 return CMD_SUCCESS;
1220}
1221
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +01001222DEFUN(cfg_cdr_trap, cfg_cdr_trap_cmd,
1223 "cdr trap",
1224 "CDR\nEnable sending CDR via TRAP CTRL messages\n")
1225{
1226 g_cfg->cdr.trap = true;
1227 return CMD_SUCCESS;
1228}
1229
1230DEFUN(cfg_no_cdr_trap, cfg_no_cdr_trap_cmd,
1231 "no cdr trap",
1232 NO_STR "CDR\nDisable sending CDR via TRAP CTRL messages\n")
1233{
1234 g_cfg->cdr.trap = false;
1235 return CMD_SUCCESS;
1236}
1237
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001238DEFUN(cfg_cdr_interval, cfg_cdr_interval_cmd,
1239 "cdr interval <1-2147483647>",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001240 "CDR\n"
1241 "Set the interval for the call-data-record file\n"
1242 "interval in seconds\n")
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001243{
1244 g_cfg->cdr.interval = atoi(argv[0]);
1245 return CMD_SUCCESS;
1246}
1247
Philippf1f34362016-08-26 17:00:21 +02001248#define COMPRESSION_STR "Configure compression\n"
1249DEFUN(cfg_no_comp_rfc1144, cfg_no_comp_rfc1144_cmd,
1250 "no compression rfc1144",
1251 NO_STR COMPRESSION_STR "disable rfc1144 TCP/IP header compression\n")
1252{
1253 g_cfg->pcomp_rfc1144.active = 0;
1254 g_cfg->pcomp_rfc1144.passive = 0;
1255 return CMD_SUCCESS;
1256}
1257
1258DEFUN(cfg_comp_rfc1144, cfg_comp_rfc1144_cmd,
1259 "compression rfc1144 active slots <1-256>",
1260 COMPRESSION_STR
1261 "RFC1144 Header compresion scheme\n"
1262 "Compression is actively proposed\n"
1263 "Number of compression state slots\n"
1264 "Number of compression state slots\n")
1265{
1266 g_cfg->pcomp_rfc1144.active = 1;
1267 g_cfg->pcomp_rfc1144.passive = 1;
1268 g_cfg->pcomp_rfc1144.s01 = atoi(argv[0]) - 1;
1269 return CMD_SUCCESS;
1270}
1271
1272DEFUN(cfg_comp_rfc1144p, cfg_comp_rfc1144p_cmd,
1273 "compression rfc1144 passive",
1274 COMPRESSION_STR
1275 "RFC1144 Header compresion scheme\n"
1276 "Compression is available on request\n")
1277{
1278 g_cfg->pcomp_rfc1144.active = 0;
1279 g_cfg->pcomp_rfc1144.passive = 1;
1280 return CMD_SUCCESS;
1281}
1282
Philipp73f83d52016-09-02 13:38:01 +02001283DEFUN(cfg_no_comp_v42bis, cfg_no_comp_v42bis_cmd,
1284 "no compression v42bis",
1285 NO_STR COMPRESSION_STR "disable V.42bis data compression\n")
1286{
1287 g_cfg->dcomp_v42bis.active = 0;
1288 g_cfg->dcomp_v42bis.passive = 0;
1289 return CMD_SUCCESS;
1290}
1291
1292DEFUN(cfg_comp_v42bis, cfg_comp_v42bis_cmd,
1293 "compression v42bis active direction (ms|sgsn|both) codewords <512-65535> strlen <6-250>",
1294 COMPRESSION_STR
1295 "V.42bis data compresion scheme\n"
1296 "Compression is actively proposed\n"
1297 "Direction in which the compression shall be active (p0)\n"
1298 "Compress ms->sgsn direction only\n"
1299 "Compress sgsn->ms direction only\n"
1300 "Both directions\n"
1301 "Number of codewords (p1)\n"
1302 "Number of codewords\n"
1303 "Maximum string length (p2)\n" "Maximum string length\n")
1304{
1305 g_cfg->dcomp_v42bis.active = 1;
1306 g_cfg->dcomp_v42bis.passive = 1;
1307
1308 switch (argv[0][0]) {
1309 case 'm':
1310 g_cfg->dcomp_v42bis.p0 = 1;
1311 break;
1312 case 's':
1313 g_cfg->dcomp_v42bis.p0 = 2;
1314 break;
1315 case 'b':
1316 g_cfg->dcomp_v42bis.p0 = 3;
1317 break;
1318 }
1319
1320 g_cfg->dcomp_v42bis.p1 = atoi(argv[1]);
1321 g_cfg->dcomp_v42bis.p2 = atoi(argv[2]);
1322 return CMD_SUCCESS;
1323}
1324
1325DEFUN(cfg_comp_v42bisp, cfg_comp_v42bisp_cmd,
1326 "compression v42bis passive",
1327 COMPRESSION_STR
1328 "V.42bis data compresion scheme\n"
1329 "Compression is available on request\n")
1330{
1331 g_cfg->dcomp_v42bis.active = 0;
1332 g_cfg->dcomp_v42bis.passive = 1;
1333 return CMD_SUCCESS;
1334}
1335
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001336int sgsn_vty_init(struct sgsn_config *cfg)
Harald Welte288be162010-05-01 16:48:27 +02001337{
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001338 g_cfg = cfg;
1339
Harald Welted193cb32010-05-17 22:58:03 +02001340 install_element_ve(&show_sgsn_cmd);
1341 //install_element_ve(&show_mmctx_tlli_cmd);
1342 install_element_ve(&show_mmctx_imsi_cmd);
1343 install_element_ve(&show_mmctx_all_cmd);
1344 install_element_ve(&show_pdpctx_all_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001345 install_element_ve(&show_subscr_cache_cmd);
1346
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01001347 install_element(ENABLE_NODE, &update_subscr_insert_auth_triplet_cmd);
Jacob Erlbeckd9193432015-01-19 14:11:46 +01001348 install_element(ENABLE_NODE, &update_subscr_create_cmd);
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001349 install_element(ENABLE_NODE, &update_subscr_destroy_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001350 install_element(ENABLE_NODE, &update_subscr_cancel_cmd);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001351 install_element(ENABLE_NODE, &update_subscr_update_location_result_cmd);
1352 install_element(ENABLE_NODE, &update_subscr_update_auth_info_cmd);
Alexander Couzensc503f0a2018-08-07 17:50:04 +02001353 install_element(ENABLE_NODE, &reset_sgsn_state_cmd);
Harald Welte288be162010-05-01 16:48:27 +02001354
1355 install_element(CONFIG_NODE, &cfg_sgsn_cmd);
1356 install_node(&sgsn_node, config_write_sgsn);
Harald Weltee300d002010-06-02 12:41:34 +02001357 install_element(SGSN_NODE, &cfg_sgsn_bind_addr_cmd);
Harald Welted193cb32010-05-17 22:58:03 +02001358 install_element(SGSN_NODE, &cfg_ggsn_remote_ip_cmd);
1359 //install_element(SGSN_NODE, &cfg_ggsn_remote_port_cmd);
1360 install_element(SGSN_NODE, &cfg_ggsn_gtp_version_cmd);
Pau Espin Pedrolfa120102018-07-09 20:37:47 +02001361 install_element(SGSN_NODE, &cfg_ggsn_echo_interval_cmd);
Pau Espin Pedrola83850c2018-07-10 12:43:59 +02001362 install_element(SGSN_NODE, &cfg_ggsn_no_echo_interval_cmd);
Harald Welte7f6da482013-03-19 11:00:13 +01001363 install_element(SGSN_NODE, &cfg_imsi_acl_cmd);
Harald Welte3dfb5492013-03-19 11:48:54 +01001364 install_element(SGSN_NODE, &cfg_auth_policy_cmd);
Max93408ae2016-06-28 14:10:16 +02001365 install_element(SGSN_NODE, &cfg_encrypt_cmd);
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001366 install_element(SGSN_NODE, &cfg_gsup_remote_ip_cmd);
1367 install_element(SGSN_NODE, &cfg_gsup_remote_port_cmd);
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001368 install_element(SGSN_NODE, &cfg_gsup_oap_id_cmd);
1369 install_element(SGSN_NODE, &cfg_gsup_oap_k_cmd);
1370 install_element(SGSN_NODE, &cfg_gsup_oap_opc_cmd);
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +01001371 install_element(SGSN_NODE, &cfg_apn_ggsn_cmd);
1372 install_element(SGSN_NODE, &cfg_apn_imsi_ggsn_cmd);
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001373 install_element(SGSN_NODE, &cfg_apn_name_cmd);
1374 install_element(SGSN_NODE, &cfg_no_apn_name_cmd);
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001375 install_element(SGSN_NODE, &cfg_cdr_filename_cmd);
1376 install_element(SGSN_NODE, &cfg_no_cdr_filename_cmd);
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +01001377 install_element(SGSN_NODE, &cfg_cdr_trap_cmd);
1378 install_element(SGSN_NODE, &cfg_no_cdr_trap_cmd);
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001379 install_element(SGSN_NODE, &cfg_cdr_interval_cmd);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001380 install_element(SGSN_NODE, &cfg_ggsn_dynamic_lookup_cmd);
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +08001381 install_element(SGSN_NODE, &cfg_grx_ggsn_cmd);
Harald Welte288be162010-05-01 16:48:27 +02001382
Harald Welte94508822015-08-15 19:08:21 +02001383 install_element(SGSN_NODE, &cfg_sgsn_T3312_cmd);
1384 install_element(SGSN_NODE, &cfg_sgsn_T3322_cmd);
1385 install_element(SGSN_NODE, &cfg_sgsn_T3350_cmd);
1386 install_element(SGSN_NODE, &cfg_sgsn_T3360_cmd);
1387 install_element(SGSN_NODE, &cfg_sgsn_T3370_cmd);
1388 install_element(SGSN_NODE, &cfg_sgsn_T3313_cmd);
1389 install_element(SGSN_NODE, &cfg_sgsn_T3314_cmd);
1390 install_element(SGSN_NODE, &cfg_sgsn_T3316_cmd);
1391 install_element(SGSN_NODE, &cfg_sgsn_T3385_cmd);
1392 install_element(SGSN_NODE, &cfg_sgsn_T3386_cmd);
1393 install_element(SGSN_NODE, &cfg_sgsn_T3395_cmd);
1394 install_element(SGSN_NODE, &cfg_sgsn_T3397_cmd);
1395
Philippf1f34362016-08-26 17:00:21 +02001396 install_element(SGSN_NODE, &cfg_no_comp_rfc1144_cmd);
1397 install_element(SGSN_NODE, &cfg_comp_rfc1144_cmd);
1398 install_element(SGSN_NODE, &cfg_comp_rfc1144p_cmd);
Philipp73f83d52016-09-02 13:38:01 +02001399 install_element(SGSN_NODE, &cfg_no_comp_v42bis_cmd);
1400 install_element(SGSN_NODE, &cfg_comp_v42bis_cmd);
1401 install_element(SGSN_NODE, &cfg_comp_v42bisp_cmd);
Neels Hofmeyr2188a772016-05-20 21:59:55 +02001402
1403#ifdef BUILD_IU
Neels Hofmeyra7a39472017-07-05 15:19:52 +02001404 ranap_iu_vty_init(SGSN_NODE, &g_cfg->iu.rab_assign_addr_enc);
Neels Hofmeyr2188a772016-05-20 21:59:55 +02001405#endif
Harald Welte288be162010-05-01 16:48:27 +02001406 return 0;
1407}
1408
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001409int sgsn_parse_config(const char *config_file)
Harald Welte288be162010-05-01 16:48:27 +02001410{
1411 int rc;
1412
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001413 /* make sure sgsn_vty_init() was called before this */
1414 OSMO_ASSERT(g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +01001415
Harald Welte94508822015-08-15 19:08:21 +02001416 g_cfg->timers.T3312 = GSM0408_T3312_SECS;
1417 g_cfg->timers.T3322 = GSM0408_T3322_SECS;
1418 g_cfg->timers.T3350 = GSM0408_T3350_SECS;
1419 g_cfg->timers.T3360 = GSM0408_T3360_SECS;
1420 g_cfg->timers.T3370 = GSM0408_T3370_SECS;
1421 g_cfg->timers.T3313 = GSM0408_T3313_SECS;
1422 g_cfg->timers.T3314 = GSM0408_T3314_SECS;
1423 g_cfg->timers.T3316 = GSM0408_T3316_SECS;
1424 g_cfg->timers.T3385 = GSM0408_T3385_SECS;
1425 g_cfg->timers.T3386 = GSM0408_T3386_SECS;
1426 g_cfg->timers.T3395 = GSM0408_T3395_SECS;
1427 g_cfg->timers.T3397 = GSM0408_T3397_SECS;
1428
Harald Weltedcccb182010-05-16 20:52:23 +02001429 rc = vty_read_config_file(config_file, NULL);
Harald Welte288be162010-05-01 16:48:27 +02001430 if (rc < 0) {
1431 fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
1432 return rc;
1433 }
1434
Neels Hofmeyr27355c92017-02-24 06:28:31 +01001435 if (g_cfg->auth_policy == SGSN_AUTH_POLICY_REMOTE
1436 && !(g_cfg->gsup_server_addr.sin_addr.s_addr
1437 && g_cfg->gsup_server_port)) {
1438 fprintf(stderr, "Configuration error:"
1439 " 'auth-policy remote' requires both"
1440 " 'gsup remote-ip' and 'gsup remote-port'\n");
1441 return -EINVAL;
1442 }
1443
Harald Welte288be162010-05-01 16:48:27 +02001444 return 0;
1445}