blob: 3b2a04a856128608a7aa76ef6b93ab55dfb747d0 [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>
Pau Espin Pedrola299d652019-08-14 19:11:10 +020031#include <osmocom/core/tdef.h>
Harald Welte53373bc2016-04-20 17:11:43 +020032#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
Harald Welte7e82b742017-08-12 13:43:54 +020033#include <osmocom/gsm/apn.h>
Harald Welte288be162010-05-01 16:48:27 +020034
Neels Hofmeyr396f2e62017-09-04 15:13:25 +020035#include <osmocom/sgsn/debug.h>
36#include <osmocom/sgsn/sgsn.h>
Alexander Couzensf23e2db2020-07-27 22:39:58 +020037#include <osmocom/gprs/gprs_ns2.h>
Alexander Couzensc503f0a2018-08-07 17:50:04 +020038#include <osmocom/sgsn/gprs_gmm.h>
Neels Hofmeyr396f2e62017-09-04 15:13:25 +020039#include <osmocom/sgsn/gprs_sgsn.h>
Pau Espin Pedrole5c89982021-05-03 18:16:42 +020040#include <osmocom/sgsn/gtp_mme.h>
Neels Hofmeyr396f2e62017-09-04 15:13:25 +020041#include <osmocom/sgsn/vty.h>
Harald Weltef4b2c4c2018-09-16 07:53:41 +020042#include <osmocom/gsupclient/gsup_client.h>
Harald Welte288be162010-05-01 16:48:27 +020043
Pau Espin Pedrola299d652019-08-14 19:11:10 +020044#include <osmocom/vty/tdef_vty.h>
Harald Welte4b037e42010-05-19 19:45:32 +020045#include <osmocom/vty/command.h>
46#include <osmocom/vty/vty.h>
Pablo Neira Ayuso6110a3f2011-03-28 19:35:00 +020047#include <osmocom/vty/misc.h>
Max93408ae2016-06-28 14:10:16 +020048#include <osmocom/crypt/gprs_cipher.h>
Jacob Erlbeck80547992014-12-19 19:19:46 +010049#include <osmocom/abis/ipa.h>
50
Alexander Couzensc503f0a2018-08-07 17:50:04 +020051#include <osmocom/gprs/gprs_bssgp.h>
52
Harald Welted193cb32010-05-17 22:58:03 +020053#include <pdp.h>
Maxbaabc682017-10-20 13:39:57 +020054#include <gtp.h>
Harald Welted193cb32010-05-17 22:58:03 +020055
Neels Hofmeyr2188a772016-05-20 21:59:55 +020056#include "../../bscconfig.h"
57
58#ifdef BUILD_IU
Neels Hofmeyra7a39472017-07-05 15:19:52 +020059#include <osmocom/ranap/iu_client.h>
Neels Hofmeyr2188a772016-05-20 21:59:55 +020060#endif
61
Pau Espin Pedrolb1d1c242018-10-30 17:27:59 +010062extern void *tall_sgsn_ctx;
Neels Hofmeyree6cfdc2017-07-13 02:03:50 +020063
Harald Welte288be162010-05-01 16:48:27 +020064static struct sgsn_config *g_cfg = NULL;
65
Jacob Erlbeck106f5472014-11-04 10:08:37 +010066const struct value_string sgsn_auth_pol_strs[] = {
67 { SGSN_AUTH_POLICY_OPEN, "accept-all" },
68 { SGSN_AUTH_POLICY_CLOSED, "closed" },
69 { SGSN_AUTH_POLICY_ACL_ONLY, "acl-only" },
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +010070 { SGSN_AUTH_POLICY_REMOTE, "remote" },
Jacob Erlbeck106f5472014-11-04 10:08:37 +010071 { 0, NULL }
72};
73
Harald Welte94508822015-08-15 19:08:21 +020074/* Section 11.2.2 / Table 11.3a GPRS Mobility management timers – MS side */
75#define GSM0408_T3312_SECS (10*60) /* periodic RAU interval, default 54min */
76
77/* Section 11.2.2 / Table 11.4 MM timers netwokr side */
78#define GSM0408_T3322_SECS 6 /* DETACH_REQ -> DETACH_ACC */
79#define GSM0408_T3350_SECS 6 /* waiting for ATT/RAU/TMSI COMPL */
80#define GSM0408_T3360_SECS 6 /* waiting for AUTH/CIPH RESP */
81#define GSM0408_T3370_SECS 6 /* waiting for ID RESP */
82
Alexander Couzens5ba6fb32017-01-31 18:04:27 +010083/* Section 11.2.2 / Table 11.4a MM timers network side */
Harald Welte94508822015-08-15 19:08:21 +020084#define GSM0408_T3313_SECS 30 /* waiting for paging response */
85#define GSM0408_T3314_SECS 44 /* force to STBY on expiry, Ready timer */
86#define GSM0408_T3316_SECS 44
87
88/* Section 11.3 / Table 11.2d Timers of Session Management - network side */
89#define GSM0408_T3385_SECS 8 /* wait for ACT PDP CTX REQ */
90#define GSM0408_T3386_SECS 8 /* wait for MODIFY PDP CTX ACK */
91#define GSM0408_T3395_SECS 8 /* wait for DEACT PDP CTX ACK */
92#define GSM0408_T3397_SECS 8 /* wait for DEACT AA PDP CTX ACK */
93
Alexander Couzensafadd102019-10-08 14:30:59 +020094/* Non spec timer */
95#define NONSPEC_X1001_SECS 5 /* wait for a RANAP Release Complete */
96
Pau Espin Pedrola299d652019-08-14 19:11:10 +020097
98static struct osmo_tdef sgsn_T_defs[] = {
99 { .T=3312, .default_val=GSM0408_T3312_SECS, .desc="Periodic RA Update timer (s)" },
100 { .T=3313, .default_val=GSM0408_T3313_SECS, .desc="Waiting for paging response timer (s)" },
Alexander Couzens39cbecd2017-02-03 22:16:05 +0100101 { .T=3314, .default_val=GSM0408_T3314_SECS, .desc="READY timer. Force to STANDBY on expiry timer (s)" },
Pau Espin Pedrola299d652019-08-14 19:11:10 +0200102 { .T=3316, .default_val=GSM0408_T3316_SECS, .desc="AA-Ready timer (s)" },
103 { .T=3322, .default_val=GSM0408_T3322_SECS, .desc="Detach request -> accept timer (s)" },
104 { .T=3350, .default_val=GSM0408_T3350_SECS, .desc="Waiting for ATT/RAU/TMSI_COMPL timer (s)" },
105 { .T=3360, .default_val=GSM0408_T3360_SECS, .desc="Waiting for AUTH/CIPH response timer (s)" },
106 { .T=3370, .default_val=GSM0408_T3370_SECS, .desc="Waiting for IDENTITY response timer (s)" },
107 { .T=3385, .default_val=GSM0408_T3385_SECS, .desc="Wait for ACT PDP CTX REQ timer (s)" },
108 { .T=3386, .default_val=GSM0408_T3386_SECS, .desc="Wait for MODIFY PDP CTX ACK timer (s)" },
109 { .T=3395, .default_val=GSM0408_T3395_SECS, .desc="Wait for DEACT PDP CTX ACK timer (s)" },
110 { .T=3397, .default_val=GSM0408_T3397_SECS, .desc="Wait for DEACT AA PDP CTX ACK timer (s)" },
Alexander Couzens3bad31b2019-09-11 02:17:31 +0200111 /* non spec timers */
Alexander Couzensafadd102019-10-08 14:30:59 +0200112 { .T=-1001, .default_val=NONSPEC_X1001_SECS, .desc="RANAP Release timeout. Wait for RANAP Release Complete."
113 "On expiry release Iu connection (s)" },
Pau Espin Pedrola299d652019-08-14 19:11:10 +0200114 {}
115};
116
117DEFUN(show_timer, show_timer_cmd,
118 "show timer " OSMO_TDEF_VTY_ARG_T_OPTIONAL,
119 SHOW_STR "Show timers\n"
120 OSMO_TDEF_VTY_DOC_T)
121{
122 const char *T_arg = argc > 0 ? argv[0] : NULL;
123 return osmo_tdef_vty_show_cmd(vty, g_cfg->T_defs, T_arg, NULL);
Harald Welte94508822015-08-15 19:08:21 +0200124}
125
Pau Espin Pedrola299d652019-08-14 19:11:10 +0200126DEFUN(cfg_sgsn_timer, cfg_sgsn_timer_cmd,
127 "timer " OSMO_TDEF_VTY_ARG_SET_OPTIONAL,
128 "Configure or show timers\n"
129 OSMO_TDEF_VTY_DOC_SET)
130{
131 /* If any arguments are missing, redirect to 'show' */
132 if (argc < 2)
133 return show_timer(self, vty, argc, argv);
134 return osmo_tdef_vty_set_cmd(vty, g_cfg->T_defs, argv);
135}
Harald Welte94508822015-08-15 19:08:21 +0200136
Holger Hans Peter Freythera2730302014-03-23 18:08:26 +0100137char *gprs_pdpaddr2str(uint8_t *pdpa, uint8_t len)
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200138{
139 static char str[INET6_ADDRSTRLEN + 10];
140
141 if (!pdpa || len < 2)
142 return "none";
143
144 switch (pdpa[0] & 0x0f) {
145 case PDP_TYPE_ORG_IETF:
146 switch (pdpa[1]) {
147 case PDP_TYPE_N_IETF_IPv4:
148 if (len < 2 + 4)
149 break;
150 strcpy(str, "IPv4 ");
151 inet_ntop(AF_INET, pdpa+2, str+5, sizeof(str)-5);
152 return str;
153 case PDP_TYPE_N_IETF_IPv6:
154 if (len < 2 + 8)
155 break;
156 strcpy(str, "IPv6 ");
157 inet_ntop(AF_INET6, pdpa+2, str+5, sizeof(str)-5);
158 return str;
159 default:
160 break;
161 }
162 break;
163 case PDP_TYPE_ORG_ETSI:
164 if (pdpa[1] == PDP_TYPE_N_ETSI_PPP)
165 return "PPP";
166 break;
167 default:
168 break;
169 }
170
171 return "invalid";
172}
173
Harald Welte288be162010-05-01 16:48:27 +0200174static struct cmd_node sgsn_node = {
175 SGSN_NODE,
Harald Welte570ce242012-08-17 13:16:10 +0200176 "%s(config-sgsn)# ",
Harald Welte288be162010-05-01 16:48:27 +0200177 1,
178};
179
Pau Espin Pedrole5c89982021-05-03 18:16:42 +0200180static struct cmd_node mme_node = {
181 MME_NODE,
182 "%s(config-sgsn-mme)# ",
183 1,
184};
185
186static void config_write_mme(struct vty *vty, const struct sgsn_mme_ctx *mme, const char *prefix)
187{
188 struct mme_rim_route *rt;
189
190 vty_out(vty, "%smme %s%s", prefix, mme->name, VTY_NEWLINE);
191
192 vty_out(vty, "%s gtp remote-ip %s%s", prefix, inet_ntoa(mme->remote_addr), VTY_NEWLINE);
193 if (mme->default_route)
194 vty_out(vty, "%s gtp ran-info-relay default%s", prefix, VTY_NEWLINE);
195 llist_for_each_entry(rt, &mme->routes, list) {
196 vty_out(vty, "%s gtp ran-info-relay %s %s %u%s", prefix,
197 osmo_mcc_name(rt->tai.mcc), osmo_mnc_name(rt->tai.mnc, rt->tai.mnc_3_digits),
198 rt->tai.tac, VTY_NEWLINE);
199 }
200}
201
Harald Welte288be162010-05-01 16:48:27 +0200202static int config_write_sgsn(struct vty *vty)
203{
Harald Welte77289c22010-05-18 14:32:29 +0200204 struct sgsn_ggsn_ctx *gctx;
Harald Welte7f6da482013-03-19 11:00:13 +0100205 struct imsi_acl_entry *acl;
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100206 struct apn_ctx *actx;
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800207 struct ares_addr_node *server;
Pau Espin Pedrole5c89982021-05-03 18:16:42 +0200208 struct sgsn_mme_ctx *mme;
Harald Welte288be162010-05-01 16:48:27 +0200209
210 vty_out(vty, "sgsn%s", VTY_NEWLINE);
211
Keithc70e8382020-10-19 22:24:48 +0200212 vty_out(vty, " gtp state-dir %s%s",
213 g_cfg->gtp_statedir, VTY_NEWLINE);
Harald Weltee300d002010-06-02 12:41:34 +0200214 vty_out(vty, " gtp local-ip %s%s",
215 inet_ntoa(g_cfg->gtp_listenaddr.sin_addr), VTY_NEWLINE);
216
Harald Welted193cb32010-05-17 22:58:03 +0200217 llist_for_each_entry(gctx, &sgsn_ggsn_ctxts, list) {
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800218 if (gctx->id == UINT32_MAX)
219 continue;
220
Harald Welteff3bde82010-05-19 15:09:09 +0200221 vty_out(vty, " ggsn %u remote-ip %s%s", gctx->id,
Harald Welted193cb32010-05-17 22:58:03 +0200222 inet_ntoa(gctx->remote_addr), VTY_NEWLINE);
Harald Welteff3bde82010-05-19 15:09:09 +0200223 vty_out(vty, " ggsn %u gtp-version %u%s", gctx->id,
Harald Welted193cb32010-05-17 22:58:03 +0200224 gctx->gtp_version, VTY_NEWLINE);
Pau Espin Pedrolaa89f5d2019-08-28 16:08:45 +0200225 if (gctx->echo_interval)
226 vty_out(vty, " ggsn %u echo-interval %u%s",
Pau Espin Pedrolfa120102018-07-09 20:37:47 +0200227 gctx->id, gctx->echo_interval, VTY_NEWLINE);
Pau Espin Pedrola83850c2018-07-10 12:43:59 +0200228 else
229 vty_out(vty, " ggsn %u no echo-interval%s",
230 gctx->id, VTY_NEWLINE);
Harald Welte288be162010-05-01 16:48:27 +0200231 }
232
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800233 if (sgsn->cfg.dynamic_lookup)
234 vty_out(vty, " ggsn dynamic%s", VTY_NEWLINE);
235
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800236 for (server = sgsn->ares_servers; server; server = server->next)
237 vty_out(vty, " grx-dns-add %s%s", inet_ntoa(server->addr.addr4), VTY_NEWLINE);
238
Max93408ae2016-06-28 14:10:16 +0200239 if (g_cfg->cipher != GPRS_ALGO_GEA0)
240 vty_out(vty, " encryption %s%s",
241 get_value_string(gprs_cipher_names, g_cfg->cipher),
242 VTY_NEWLINE);
Stefan Sperling88220092018-12-11 14:42:00 +0100243 if (g_cfg->sgsn_ipa_name)
244 vty_out(vty, " gsup ipa-name %s%s", g_cfg->sgsn_ipa_name, VTY_NEWLINE);
Jacob Erlbeck39f040d2014-12-18 12:46:47 +0100245 if (g_cfg->gsup_server_addr.sin_addr.s_addr)
246 vty_out(vty, " gsup remote-ip %s%s",
247 inet_ntoa(g_cfg->gsup_server_addr.sin_addr), VTY_NEWLINE);
248 if (g_cfg->gsup_server_port)
249 vty_out(vty, " gsup remote-port %d%s",
250 g_cfg->gsup_server_port, VTY_NEWLINE);
Pau Espin Pedrold1463bc2019-06-13 19:03:25 +0200251 if (g_cfg->auth_policy == SGSN_AUTH_POLICY_REMOTE && !g_cfg->require_authentication)
252 vty_out(vty, " authentication optional%s", VTY_NEWLINE);
Max176b62a2016-07-04 11:09:07 +0200253 vty_out(vty, " auth-policy %s%s",
254 get_value_string(sgsn_auth_pol_strs, g_cfg->auth_policy),
255 VTY_NEWLINE);
Neels Hofmeyr568a7272015-10-12 11:57:38 +0200256
257 vty_out(vty, " gsup oap-id %d%s",
258 (int)g_cfg->oap.client_id, VTY_NEWLINE);
259 if (g_cfg->oap.secret_k_present != 0)
260 vty_out(vty, " gsup oap-k %s%s",
261 osmo_hexdump_nospc(g_cfg->oap.secret_k, sizeof(g_cfg->oap.secret_k)),
262 VTY_NEWLINE);
263 if (g_cfg->oap.secret_opc_present != 0)
264 vty_out(vty, " gsup oap-opc %s%s",
265 osmo_hexdump_nospc(g_cfg->oap.secret_opc, sizeof(g_cfg->oap.secret_opc)),
266 VTY_NEWLINE);
267
Harald Welte7f6da482013-03-19 11:00:13 +0100268 llist_for_each_entry(acl, &g_cfg->imsi_acl, list)
269 vty_out(vty, " imsi-acl add %s%s", acl->imsi, VTY_NEWLINE);
270
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100271 if (llist_empty(&sgsn_apn_ctxts))
272 vty_out(vty, " ! apn * ggsn 0%s", VTY_NEWLINE);
273 llist_for_each_entry(actx, &sgsn_apn_ctxts, list) {
274 if (strlen(actx->imsi_prefix) > 0)
Holger Hans Peter Freytherb7ae0b32015-05-29 15:11:55 +0200275 vty_out(vty, " apn %s imsi-prefix %s ggsn %u%s",
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100276 actx->name, actx->imsi_prefix, actx->ggsn->id,
277 VTY_NEWLINE);
278 else
Holger Hans Peter Freytherb7ae0b32015-05-29 15:11:55 +0200279 vty_out(vty, " apn %s ggsn %u%s", actx->name,
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100280 actx->ggsn->id, VTY_NEWLINE);
281 }
282
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +0200283 if (g_cfg->cdr.filename)
284 vty_out(vty, " cdr filename %s%s", g_cfg->cdr.filename, VTY_NEWLINE);
285 else
286 vty_out(vty, " no cdr filename%s", VTY_NEWLINE);
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +0100287 if (g_cfg->cdr.trap)
288 vty_out(vty, " cdr trap%s", VTY_NEWLINE);
289 else
290 vty_out(vty, " no cdr trap%s", VTY_NEWLINE);
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +0200291 vty_out(vty, " cdr interval %d%s", g_cfg->cdr.interval, VTY_NEWLINE);
292
Pau Espin Pedrola299d652019-08-14 19:11:10 +0200293 osmo_tdef_vty_write(vty, g_cfg->T_defs, " timer ");
Harald Welte94508822015-08-15 19:08:21 +0200294
Philippf1f34362016-08-26 17:00:21 +0200295 if (g_cfg->pcomp_rfc1144.active) {
296 vty_out(vty, " compression rfc1144 active slots %d%s",
297 g_cfg->pcomp_rfc1144.s01 + 1, VTY_NEWLINE);
298 } else if (g_cfg->pcomp_rfc1144.passive) {
299 vty_out(vty, " compression rfc1144 passive%s", VTY_NEWLINE);
300 } else
301 vty_out(vty, " no compression rfc1144%s", VTY_NEWLINE);
302
Philipp73f83d52016-09-02 13:38:01 +0200303 if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 1) {
304 vty_out(vty,
305 " compression v42bis active direction sgsn codewords %d strlen %d%s",
306 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
307 VTY_NEWLINE);
308 } else if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 2) {
309 vty_out(vty,
310 " compression v42bis active direction ms codewords %d strlen %d%s",
311 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
312 VTY_NEWLINE);
313 } else if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 3) {
314 vty_out(vty,
315 " compression v42bis active direction both codewords %d strlen %d%s",
316 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
317 VTY_NEWLINE);
318 } else if (g_cfg->dcomp_v42bis.passive) {
319 vty_out(vty, " compression v42bis passive%s", VTY_NEWLINE);
320 } else
321 vty_out(vty, " no compression v42bis%s", VTY_NEWLINE);
322
Pau Espin Pedrole5c89982021-05-03 18:16:42 +0200323 llist_for_each_entry(mme, &sgsn->mme_list, list) {
324 config_write_mme(vty, mme, " ");
325 }
326
Neels Hofmeyr2188a772016-05-20 21:59:55 +0200327#ifdef BUILD_IU
Pau Espin Pedrol2c908992019-08-19 19:06:06 +0200328 vty_out(vty, " cs7-instance-iu %u%s", g_cfg->iu.cs7_instance,
329 VTY_NEWLINE);
Neels Hofmeyra7a39472017-07-05 15:19:52 +0200330 ranap_iu_vty_config_write(vty, " ");
Neels Hofmeyr2188a772016-05-20 21:59:55 +0200331#endif
332
Harald Welte288be162010-05-01 16:48:27 +0200333 return CMD_SUCCESS;
334}
335
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100336#define SGSN_STR "Configure the SGSN\n"
337#define GGSN_STR "Configure the GGSN information\n"
Harald Weltee300d002010-06-02 12:41:34 +0200338
339DEFUN(cfg_sgsn, cfg_sgsn_cmd,
340 "sgsn",
341 SGSN_STR)
Harald Welte288be162010-05-01 16:48:27 +0200342{
343 vty->node = SGSN_NODE;
344 return CMD_SUCCESS;
345}
346
Keithc70e8382020-10-19 22:24:48 +0200347DEFUN(cfg_sgsn_state_dir, cfg_sgsn_state_dir_cmd,
348 "gtp state-dir PATH",
349 "GTP Parameters\n"
350 "Set the directory for the GTP State file\n"
351 "Local Directory\n")
352{
353 osmo_talloc_replace_string(sgsn, &sgsn->cfg.gtp_statedir, argv[0]);
354
355 return CMD_SUCCESS;
356}
357
Harald Weltee300d002010-06-02 12:41:34 +0200358DEFUN(cfg_sgsn_bind_addr, cfg_sgsn_bind_addr_cmd,
359 "gtp local-ip A.B.C.D",
360 "GTP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100361 "Set the IP address for the local GTP bind for the Gp interface (towards the GGSNs)."
362 " Note: in case you would like to run the GGSN on the same machine as the SGSN, you can not run"
363 " both on the same IP address, since both sides are specified to use the same GTP port numbers"
364 " (" OSMO_STRINGIFY_VAL(GTP1C_PORT) " and " OSMO_STRINGIFY_VAL(GTP1U_PORT) ")."
365 " For example, you could use 127.0.0.1 for the SGSN and 127.0.0.2 for the GGSN in such"
366 " situations.\n"
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100367 "IPv4 Address\n")
Harald Weltee300d002010-06-02 12:41:34 +0200368{
369 inet_aton(argv[0], &g_cfg->gtp_listenaddr.sin_addr);
370
371 return CMD_SUCCESS;
372}
373
Harald Welted193cb32010-05-17 22:58:03 +0200374DEFUN(cfg_ggsn_remote_ip, cfg_ggsn_remote_ip_cmd,
375 "ggsn <0-255> remote-ip A.B.C.D",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100376 GGSN_STR "GGSN Number\n"
377 "Configure this static GGSN to use the specified remote IP address.\n"
378 "IPv4 Address\n")
Harald Welted193cb32010-05-17 22:58:03 +0200379{
380 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200381 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welte288be162010-05-01 16:48:27 +0200382
Harald Welted193cb32010-05-17 22:58:03 +0200383 inet_aton(argv[1], &ggc->remote_addr);
Harald Welte288be162010-05-01 16:48:27 +0200384
Harald Welted193cb32010-05-17 22:58:03 +0200385 return CMD_SUCCESS;
386}
387
388#if 0
389DEFUN(cfg_ggsn_remote_port, cfg_ggsn_remote_port_cmd,
390 "ggsn <0-255> remote-port <0-65535>",
391 "")
392{
393 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200394 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welted193cb32010-05-17 22:58:03 +0200395 uint16_t port = atoi(argv[1]);
396
397}
398#endif
399
400DEFUN(cfg_ggsn_gtp_version, cfg_ggsn_gtp_version_cmd,
401 "ggsn <0-255> gtp-version (0|1)",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100402 GGSN_STR "GGSN Number\n" "GTP Version\n"
403 "Version 0\n" "Version 1\n")
Harald Welted193cb32010-05-17 22:58:03 +0200404{
405 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200406 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welted193cb32010-05-17 22:58:03 +0200407
408 if (atoi(argv[1]))
409 ggc->gtp_version = 1;
410 else
411 ggc->gtp_version = 0;
412
413 return CMD_SUCCESS;
414}
415
Pau Espin Pedrolfa120102018-07-09 20:37:47 +0200416/* Seee 3GPP TS 29.060 section 7.2.1 */
417DEFUN(cfg_ggsn_echo_interval, cfg_ggsn_echo_interval_cmd,
418 "ggsn <0-255> echo-interval <1-36000>",
419 GGSN_STR "GGSN Number\n"
420 "Send an echo request to this static GGSN every interval.\n"
421 "Interval between echo requests in seconds.\n")
422{
423 uint32_t id = atoi(argv[0]);
424 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
425
426 ggc->echo_interval = atoi(argv[1]);
427
428 if (ggc->echo_interval < 60)
Pau Espin Pedrolba2e5002019-05-27 17:35:32 +0200429 vty_out(vty, "%% 3GPP TS 29.060 section 7.2.1 states interval should " \
Pau Espin Pedrolfa120102018-07-09 20:37:47 +0200430 "not be lower than 60 seconds, use this value for " \
431 "testing purposes only!%s", VTY_NEWLINE);
432
Alexander Couzens176a4d22018-09-18 20:07:37 +0200433 sgsn_ggsn_ctx_check_echo_timer(ggc);
Pau Espin Pedrolfa120102018-07-09 20:37:47 +0200434 return CMD_SUCCESS;
435}
436
Pau Espin Pedrola83850c2018-07-10 12:43:59 +0200437DEFUN(cfg_ggsn_no_echo_interval, cfg_ggsn_no_echo_interval_cmd,
438 "ggsn <0-255> no echo-interval",
439 GGSN_STR "GGSN Number\n"
440 NO_STR "Send an echo request to this static GGSN every interval.\n")
441{
442 uint32_t id = atoi(argv[0]);
443 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
444
Pau Espin Pedrolaa89f5d2019-08-28 16:08:45 +0200445 ggc->echo_interval = 0;
Alexander Couzens176a4d22018-09-18 20:07:37 +0200446 sgsn_ggsn_ctx_check_echo_timer(ggc);
Pau Espin Pedrola83850c2018-07-10 12:43:59 +0200447
448 return CMD_SUCCESS;
449}
450
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800451DEFUN(cfg_ggsn_dynamic_lookup, cfg_ggsn_dynamic_lookup_cmd,
452 "ggsn dynamic",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100453 GGSN_STR
454 "Enable dynamic resolving of GGSNs based on DNS resolving the APN name like in a GRX-style setup."
455 " Changing this setting requires a restart.\n")
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800456{
457 sgsn->cfg.dynamic_lookup = 1;
458 return CMD_SUCCESS;
459}
460
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800461DEFUN(cfg_grx_ggsn, cfg_grx_ggsn_cmd,
462 "grx-dns-add A.B.C.D",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100463 "Use the specified IP address for DNS-resolving the AP names to GGSN IP addresses\n"
464 "IPv4 address\n")
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800465{
Pau Espin Pedrolb1d1c242018-10-30 17:27:59 +0100466 struct ares_addr_node *node = talloc_zero(tall_sgsn_ctx, struct ares_addr_node);
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800467 node->family = AF_INET;
468 inet_aton(argv[0], &node->addr.addr4);
469
470 node->next = sgsn->ares_servers;
471 sgsn->ares_servers = node;
472 return CMD_SUCCESS;
473}
474
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100475#define APN_STR "Configure the information per APN\n"
476#define APN_GW_STR "The APN gateway name optionally prefixed by '*' (wildcard)\n"
477
478static int add_apn_ggsn_mapping(struct vty *vty, const char *apn_str,
479 const char *imsi_prefix, int ggsn_id)
480{
481 struct apn_ctx *actx;
482 struct sgsn_ggsn_ctx *ggsn;
483
484 ggsn = sgsn_ggsn_ctx_by_id(ggsn_id);
485 if (ggsn == NULL) {
486 vty_out(vty, "%% a GGSN with id %d has not been defined%s",
487 ggsn_id, VTY_NEWLINE);
488 return CMD_WARNING;
489 }
490
491 actx = sgsn_apn_ctx_find_alloc(apn_str, imsi_prefix);
492 if (!actx) {
493 vty_out(vty, "%% unable to create APN context for %s/%s%s",
494 apn_str, imsi_prefix, VTY_NEWLINE);
495 return CMD_WARNING;
496 }
497
498 actx->ggsn = ggsn;
499
500 return CMD_SUCCESS;
501}
502
Harald Welted193cb32010-05-17 22:58:03 +0200503DEFUN(cfg_apn_ggsn, cfg_apn_ggsn_cmd,
504 "apn APNAME ggsn <0-255>",
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100505 APN_STR APN_GW_STR
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100506 "Select the GGSN to use for the given APN gateway prefix\n"
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100507 "The GGSN id")
Harald Welted193cb32010-05-17 22:58:03 +0200508{
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100509
510 return add_apn_ggsn_mapping(vty, argv[0], "", atoi(argv[1]));
Harald Welted193cb32010-05-17 22:58:03 +0200511}
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100512
513DEFUN(cfg_apn_imsi_ggsn, cfg_apn_imsi_ggsn_cmd,
514 "apn APNAME imsi-prefix IMSIPRE ggsn <0-255>",
515 APN_STR APN_GW_STR
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100516 "Select the GGSN to use for the given APN gateway prefix if and only if the IMSI matches the"
517 " given prefix.\n"
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100518 "An IMSI prefix\n"
519 "Select the GGSN to use when APN gateway and IMSI prefix match\n"
520 "The GGSN id")
521{
522
523 return add_apn_ggsn_mapping(vty, argv[0], argv[1], atoi(argv[2]));
524}
Harald Welted193cb32010-05-17 22:58:03 +0200525
Maxc005db72017-10-27 18:43:29 +0200526char *sgsn_gtp_ntoa(struct ul16_t *ul)
Harald Welte471ac7d2016-12-15 19:48:58 +0100527{
Max8492c202017-12-05 17:28:15 +0100528 struct in_addr ia;
529
530 if (gsna2in_addr(&ia, ul) != 0)
Harald Welte471ac7d2016-12-15 19:48:58 +0100531 return "UNKNOWN";
Max8492c202017-12-05 17:28:15 +0100532
533 return inet_ntoa(ia);
Harald Welte471ac7d2016-12-15 19:48:58 +0100534}
535
Harald Welted193cb32010-05-17 22:58:03 +0200536static void vty_dump_pdp(struct vty *vty, const char *pfx,
537 struct sgsn_pdp_ctx *pdp)
538{
Jacob Erlbeck99985b52014-10-13 10:32:00 +0200539 const char *imsi = pdp->mm ? pdp->mm->imsi : "(detaching)";
Harald Welte471ac7d2016-12-15 19:48:58 +0100540 vty_out(vty, "%sPDP Context IMSI: %s, SAPI: %u, NSAPI: %u, TI: %u%s",
541 pfx, imsi, pdp->sapi, pdp->nsapi, pdp->ti, VTY_NEWLINE);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200542 if (pdp->lib) {
Max7933d962017-10-19 16:52:30 +0200543 char apnbuf[APN_MAXLEN + 1];
Harald Weltedfbd2c82017-08-13 00:56:45 +0200544 vty_out(vty, "%s APN: %s%s", pfx,
Max7933d962017-10-19 16:52:30 +0200545 osmo_apn_to_str(apnbuf, pdp->lib->apn_use.v, pdp->lib->apn_use.l),
Harald Weltedfbd2c82017-08-13 00:56:45 +0200546 VTY_NEWLINE);
547 vty_out(vty, "%s PDP Address: %s%s", pfx,
548 gprs_pdpaddr2str(pdp->lib->eua.v, pdp->lib->eua.l),
549 VTY_NEWLINE);
Maxb24af2b2017-12-05 17:54:42 +0100550 vty_out(vty, "%s GTPv%d Local Control(%s / TEIC: 0x%08x) ", pfx, pdp->lib->version,
Maxc005db72017-10-27 18:43:29 +0200551 sgsn_gtp_ntoa(&pdp->lib->gsnlc), pdp->lib->teic_own);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200552 vty_out(vty, "Data(%s / TEID: 0x%08x)%s",
Maxc005db72017-10-27 18:43:29 +0200553 sgsn_gtp_ntoa(&pdp->lib->gsnlu), pdp->lib->teid_own, VTY_NEWLINE);
Maxb24af2b2017-12-05 17:54:42 +0100554 vty_out(vty, "%s GTPv%d Remote Control(%s / TEIC: 0x%08x) ", pfx, pdp->lib->version,
Maxc005db72017-10-27 18:43:29 +0200555 sgsn_gtp_ntoa(&pdp->lib->gsnrc), pdp->lib->teic_gn);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200556 vty_out(vty, "Data(%s / TEID: 0x%08x)%s",
Maxc005db72017-10-27 18:43:29 +0200557 sgsn_gtp_ntoa(&pdp->lib->gsnru), pdp->lib->teid_gn, VTY_NEWLINE);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200558 }
Harald Welte471ac7d2016-12-15 19:48:58 +0100559
Harald Welteefbdee92010-06-10 00:20:12 +0200560 vty_out_rate_ctr_group(vty, " ", pdp->ctrg);
Harald Welted193cb32010-05-17 22:58:03 +0200561}
562
563static void vty_dump_mmctx(struct vty *vty, const char *pfx,
564 struct sgsn_mm_ctx *mm, int pdp)
565{
Pau Espin Pedrol9119d502019-08-30 17:48:10 +0200566 uint32_t id = 0;
Pau Espin Pedrolfd815bb2019-08-30 18:32:42 +0200567 const char *mm_state_name = NULL;
Pau Espin Pedrol9119d502019-08-30 17:48:10 +0200568
569 switch(mm->ran_type) {
570 case MM_CTX_T_UTRAN_Iu:
571#if BUILD_IU
572 id = mm->iu.ue_ctx->conn_id;
Pau Espin Pedrolfd815bb2019-08-30 18:32:42 +0200573 mm_state_name = osmo_fsm_inst_state_name(mm->iu.mm_state_fsm);
Pau Espin Pedrol9119d502019-08-30 17:48:10 +0200574#endif
575 break;
576 case MM_CTX_T_GERAN_Gb:
577 id = mm->gb.tlli;
Pau Espin Pedrolfd815bb2019-08-30 18:32:42 +0200578 mm_state_name = osmo_fsm_inst_state_name(mm->gb.mm_state_fsm);
Pau Espin Pedrol9119d502019-08-30 17:48:10 +0200579 break;
580 }
581
Harald Welted193cb32010-05-17 22:58:03 +0200582 vty_out(vty, "%sMM Context for IMSI %s, IMEI %s, P-TMSI %08x%s",
583 pfx, mm->imsi, mm->imei, mm->p_tmsi, VTY_NEWLINE);
Holger Hans Peter Freyther8ee13e22015-05-18 10:00:03 +0200584 vty_out(vty, "%s MSISDN: %s, TLLI: %08x%s HLR: %s",
Pau Espin Pedrol9119d502019-08-30 17:48:10 +0200585 pfx, mm->msisdn, id, mm->hlr, VTY_NEWLINE);
Pau Espin Pedrolfd815bb2019-08-30 18:32:42 +0200586 vty_out(vty, "%s GMM State: %s, Routeing Area: %s, Cell ID: %u%s",
Pau Espin Pedrol31c46572019-09-02 16:45:27 +0200587 pfx, osmo_fsm_inst_state_name(mm->gmm_fsm),
Neels Hofmeyr10719b72018-02-21 00:39:36 +0100588 osmo_rai_name(&mm->ra), mm->gb.cell_id, VTY_NEWLINE);
Pau Espin Pedrolfd815bb2019-08-30 18:32:42 +0200589 vty_out(vty, "%s MM State: %s, RAN Type: %s%s", pfx, mm_state_name,
590 get_value_string(sgsn_ran_type_names, mm->ran_type), VTY_NEWLINE);
Harald Welted193cb32010-05-17 22:58:03 +0200591
Pau Espin Pedrol3b848bd2019-08-30 18:06:35 +0200592 vty_out_rate_ctr_group(vty, " ", mm->ctrg);
Harald Welte8acd88f2010-05-18 10:57:45 +0200593
Harald Welted193cb32010-05-17 22:58:03 +0200594 if (pdp) {
595 struct sgsn_pdp_ctx *pdp;
596
597 llist_for_each_entry(pdp, &mm->pdp_list, list)
598 vty_dump_pdp(vty, " ", pdp);
599 }
600}
601
602DEFUN(show_sgsn, show_sgsn_cmd, "show sgsn",
603 SHOW_STR "Display information about the SGSN")
604{
Jacob Erlbeck80547992014-12-19 19:19:46 +0100605 if (sgsn->gsup_client) {
606 struct ipa_client_conn *link = sgsn->gsup_client->link;
607 vty_out(vty,
608 " Remote authorization: %sconnected to %s:%d via GSUP%s",
609 sgsn->gsup_client->is_connected ? "" : "not ",
610 link->addr, link->port,
611 VTY_NEWLINE);
612 }
Maxbaabc682017-10-20 13:39:57 +0200613 if (sgsn->gsn)
614 vty_out(vty, " GSN: signalling %s, user traffic %s%s",
615 inet_ntoa(sgsn->gsn->gsnc), inet_ntoa(sgsn->gsn->gsnu), VTY_NEWLINE);
616
Harald Welted193cb32010-05-17 22:58:03 +0200617 /* FIXME: statistics */
618 return CMD_SUCCESS;
619}
620
621#define MMCTX_STR "MM Context\n"
622#define INCLUDE_PDP_STR "Include PDP Context Information\n"
623
624#if 0
625DEFUN(show_mmctx_tlli, show_mmctx_tlli_cmd,
626 "show mm-context tlli HEX [pdp]",
627 SHOW_STR MMCTX_STR "Identify by TLLI\n" "TLLI\n" INCLUDE_PDP_STR)
628{
629 uint32_t tlli;
630 struct sgsn_mm_ctx *mm;
631
632 tlli = strtoul(argv[0], NULL, 16);
633 mm = sgsn_mm_ctx_by_tlli(tlli);
634 if (!mm) {
635 vty_out(vty, "No MM context for TLLI %08x%s",
636 tlli, VTY_NEWLINE);
637 return CMD_WARNING;
638 }
639 vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
640 return CMD_SUCCESS;
641}
642#endif
643
644DEFUN(swow_mmctx_imsi, show_mmctx_imsi_cmd,
645 "show mm-context imsi IMSI [pdp]",
646 SHOW_STR MMCTX_STR "Identify by IMSI\n" "IMSI of the MM Context\n"
647 INCLUDE_PDP_STR)
648{
649 struct sgsn_mm_ctx *mm;
650
651 mm = sgsn_mm_ctx_by_imsi(argv[0]);
652 if (!mm) {
653 vty_out(vty, "No MM context for IMSI %s%s",
654 argv[0], VTY_NEWLINE);
655 return CMD_WARNING;
656 }
Keithc12c1a62021-05-20 04:41:01 +0200657 vty_dump_mmctx(vty, "", mm, (argc > 1) ? 1 : 0);
Harald Welted193cb32010-05-17 22:58:03 +0200658 return CMD_SUCCESS;
659}
660
661DEFUN(swow_mmctx_all, show_mmctx_all_cmd,
662 "show mm-context all [pdp]",
663 SHOW_STR MMCTX_STR "All MM Contexts\n" INCLUDE_PDP_STR)
664{
665 struct sgsn_mm_ctx *mm;
Harald Welted193cb32010-05-17 22:58:03 +0200666 llist_for_each_entry(mm, &sgsn_mm_ctxts, list)
Keithc12c1a62021-05-20 04:41:01 +0200667 vty_dump_mmctx(vty, "", mm, (argc > 0) ? 1 : 0);
Harald Welted193cb32010-05-17 22:58:03 +0200668
669 return CMD_SUCCESS;
670}
671
Harald Welted193cb32010-05-17 22:58:03 +0200672DEFUN(show_pdpctx_all, show_pdpctx_all_cmd,
673 "show pdp-context all",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100674 SHOW_STR "Display information on PDP Context\n" "Show everything\n")
Harald Welted193cb32010-05-17 22:58:03 +0200675{
676 struct sgsn_pdp_ctx *pdp;
677
678 llist_for_each_entry(pdp, &sgsn_pdp_ctxts, g_list)
679 vty_dump_pdp(vty, "", pdp);
680
681 return CMD_SUCCESS;
682}
Harald Welte288be162010-05-01 16:48:27 +0200683
Harald Welte7f6da482013-03-19 11:00:13 +0100684
685DEFUN(imsi_acl, cfg_imsi_acl_cmd,
686 "imsi-acl (add|del) IMSI",
687 "Access Control List of foreign IMSIs\n"
688 "Add IMSI to ACL\n"
689 "Remove IMSI from ACL\n"
690 "IMSI of subscriber\n")
691{
Maxef38b4c2018-11-20 10:25:53 +0100692 char imsi_sanitized[GSM23003_IMSI_MAX_DIGITS + 1];
Harald Welte7f6da482013-03-19 11:00:13 +0100693 const char *op = argv[0];
Philipp Maier6ee49d82017-02-28 16:53:07 +0100694 const char *imsi = imsi_sanitized;
Maxf4fa6952018-01-15 12:12:51 +0100695 size_t len = strnlen(argv[1], GSM23003_IMSI_MAX_DIGITS + 1);
Harald Welte7f6da482013-03-19 11:00:13 +0100696 int rc;
697
Maxef38b4c2018-11-20 10:25:53 +0100698 memset(imsi_sanitized, '0', GSM23003_IMSI_MAX_DIGITS);
699 imsi_sanitized[GSM23003_IMSI_MAX_DIGITS] = '\0';
700
Philipp Maier6ee49d82017-02-28 16:53:07 +0100701 /* Sanitize IMSI */
Maxf4fa6952018-01-15 12:12:51 +0100702 if (len > GSM23003_IMSI_MAX_DIGITS) {
703 vty_out(vty, "%% IMSI (%s) too long (max %u digits) -- ignored!%s",
704 argv[1], GSM23003_IMSI_MAX_DIGITS, VTY_NEWLINE);
Philipp Maier6ee49d82017-02-28 16:53:07 +0100705 return CMD_WARNING;
706 }
Maxf4fa6952018-01-15 12:12:51 +0100707
708 osmo_strlcpy(imsi_sanitized + GSM23003_IMSI_MAX_DIGITS - len, argv[1],
709 sizeof(imsi_sanitized) - (GSM23003_IMSI_MAX_DIGITS - len));
Philipp Maier6ee49d82017-02-28 16:53:07 +0100710
Harald Welte7f6da482013-03-19 11:00:13 +0100711 if (!strcmp(op, "add"))
Jacob Erlbeck3b5d4072014-10-24 15:11:03 +0200712 rc = sgsn_acl_add(imsi, g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +0100713 else
Jacob Erlbeck3b5d4072014-10-24 15:11:03 +0200714 rc = sgsn_acl_del(imsi, g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +0100715
716 if (rc < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100717 vty_out(vty, "%% unable to %s ACL%s", op, VTY_NEWLINE);
Harald Welte7f6da482013-03-19 11:00:13 +0100718 return CMD_WARNING;
719 }
720
721 return CMD_SUCCESS;
722}
723
Max93408ae2016-06-28 14:10:16 +0200724DEFUN(cfg_encrypt, cfg_encrypt_cmd,
725 "encryption (GEA0|GEA1|GEA2|GEA3|GEA4)",
726 "Set encryption algorithm for SGSN\n"
727 "Use GEA0 (no encryption)\n"
728 "Use GEA1\nUse GEA2\nUse GEA3\nUse GEA4\n")
729{
Max93408ae2016-06-28 14:10:16 +0200730 enum gprs_ciph_algo c = get_string_value(gprs_cipher_names, argv[0]);
Max086067f2017-05-02 13:03:28 +0200731 if (c != GPRS_ALGO_GEA0) {
732 if (!gprs_cipher_supported(c)) {
733 vty_out(vty, "%% cipher %s is unsupported in current version%s", argv[0], VTY_NEWLINE);
734 return CMD_WARNING;
735 }
736
737 if (!g_cfg->require_authentication) {
738 vty_out(vty, "%% unable to use encryption %s without authentication: please adjust auth-policy%s",
739 argv[0], VTY_NEWLINE);
740 return CMD_WARNING;
741 }
Max93408ae2016-06-28 14:10:16 +0200742 }
743
744 g_cfg->cipher = c;
745
746 return CMD_SUCCESS;
747}
748
Vadim Yanitskiy794f4462019-05-27 05:39:06 +0700749DEFUN(cfg_authentication, cfg_authentication_cmd,
750 "authentication (optional|required)",
Pau Espin Pedrold1463bc2019-06-13 19:03:25 +0200751 "Whether to enforce MS authentication in GERAN (only with auth-policy remote)\n"
752 "Allow MS to attach via GERAN without authentication (default and only possible value for non-remote auth-policy)\n"
753 "Always require authentication (only available for auth-policy remote, default with that auth-policy)\n")
Vadim Yanitskiy794f4462019-05-27 05:39:06 +0700754{
755 int required = (argv[0][0] == 'r');
756
757 if (vty->type != VTY_FILE) {
758 if (g_cfg->auth_policy != SGSN_AUTH_POLICY_REMOTE && required) {
759 vty_out(vty, "%% Authentication is not possible without HLR, "
760 "consider setting 'auth-policy' to 'remote'%s",
761 VTY_NEWLINE);
762 return CMD_WARNING;
763 }
764 }
765
766 g_cfg->require_authentication = required;
767 return CMD_SUCCESS;
768}
769
Harald Welte3dfb5492013-03-19 11:48:54 +0100770DEFUN(cfg_auth_policy, cfg_auth_policy_cmd,
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100771 "auth-policy (accept-all|closed|acl-only|remote)",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100772 "Configure the Authorization policy of the SGSN. This setting determines which subscribers are"
773 " permitted to register to the network.\n"
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100774 "Accept all IMSIs (DANGEROUS)\n"
775 "Accept only home network subscribers or those in the ACL\n"
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100776 "Accept only subscribers in the ACL\n"
777 "Use remote subscription data only (HLR)\n")
Harald Welte3dfb5492013-03-19 11:48:54 +0100778{
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100779 int val = get_string_value(sgsn_auth_pol_strs, argv[0]);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100780 OSMO_ASSERT(val >= SGSN_AUTH_POLICY_OPEN && val <= SGSN_AUTH_POLICY_REMOTE);
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100781 g_cfg->auth_policy = val;
Jacob Erlbeck771573c2014-12-19 18:08:48 +0100782 g_cfg->require_update_location = (val == SGSN_AUTH_POLICY_REMOTE);
Harald Welte3dfb5492013-03-19 11:48:54 +0100783
784 return CMD_SUCCESS;
785}
786
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100787/* Subscriber */
Neels Hofmeyr396f2e62017-09-04 15:13:25 +0200788#include <osmocom/sgsn/gprs_subscriber.h>
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100789
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100790static void subscr_dump_full_vty(struct vty *vty, struct gprs_subscr *gsub, int pending)
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100791{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100792#if 0
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100793 char expire_time[200];
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100794#endif
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100795 struct gsm_auth_tuple *at;
796 int at_idx;
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100797 struct sgsn_subscriber_pdp_data *pdp;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100798
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100799 vty_out(vty, " Authorized: %d%s",
800 gsub->authorized, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100801 vty_out(vty, " LAC: %d/0x%x%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100802 gsub->lac, gsub->lac, VTY_NEWLINE);
803 vty_out(vty, " IMSI: %s%s", gsub->imsi, VTY_NEWLINE);
804 if (gsub->tmsi != GSM_RESERVED_TMSI)
805 vty_out(vty, " TMSI: %08X%s", gsub->tmsi,
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100806 VTY_NEWLINE);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100807 if (gsub->sgsn_data->msisdn_len > 0)
Holger Hans Peter Freytherf7b38262015-04-23 16:58:33 -0400808 vty_out(vty, " MSISDN (BCD): %s%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100809 osmo_hexdump(gsub->sgsn_data->msisdn,
810 gsub->sgsn_data->msisdn_len),
Holger Hans Peter Freytherf7b38262015-04-23 16:58:33 -0400811 VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100812
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100813 if (strlen(gsub->imei) > 0)
814 vty_out(vty, " IMEI: %s%s", gsub->imei, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100815
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100816 for (at_idx = 0; at_idx < ARRAY_SIZE(gsub->sgsn_data->auth_triplets);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100817 at_idx++) {
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100818 at = &gsub->sgsn_data->auth_triplets[at_idx];
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100819 if (at->key_seq == GSM_KEY_SEQ_INVAL)
820 continue;
821
822 vty_out(vty, " A3A8 tuple (used %d times): ",
823 at->use_count);
Harald Welte89837d42016-05-06 23:28:11 +0200824 vty_out(vty, " CKSN: %d, ",
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100825 at->key_seq);
Harald Welte89837d42016-05-06 23:28:11 +0200826 if (at->vec.auth_types & OSMO_AUTH_TYPE_GSM) {
827 vty_out(vty, "RAND: %s, ",
Max34604c22019-02-13 14:11:29 +0100828 osmo_hexdump_nospc(at->vec.rand,
Harald Welte89837d42016-05-06 23:28:11 +0200829 sizeof(at->vec.rand)));
830 vty_out(vty, "SRES: %s, ",
Max34604c22019-02-13 14:11:29 +0100831 osmo_hexdump_nospc(at->vec.sres,
Harald Welte89837d42016-05-06 23:28:11 +0200832 sizeof(at->vec.sres)));
833 vty_out(vty, "Kc: %s%s",
Max34604c22019-02-13 14:11:29 +0100834 osmo_hexdump_nospc(at->vec.kc,
Harald Welte89837d42016-05-06 23:28:11 +0200835 sizeof(at->vec.kc)), VTY_NEWLINE);
836 }
837 if (at->vec.auth_types & OSMO_AUTH_TYPE_UMTS) {
838 vty_out(vty, " AUTN: %s, ",
839 osmo_hexdump(at->vec.autn,
840 sizeof(at->vec.autn)));
841 vty_out(vty, "RES: %s, ",
Max34604c22019-02-13 14:11:29 +0100842 osmo_hexdump_nospc(at->vec.res, at->vec.res_len));
Harald Welte89837d42016-05-06 23:28:11 +0200843 vty_out(vty, "IK: %s, ",
Max34604c22019-02-13 14:11:29 +0100844 osmo_hexdump_nospc(at->vec.ik, sizeof(at->vec.ik)));
Harald Welte89837d42016-05-06 23:28:11 +0200845 vty_out(vty, "CK: %s, ",
Max34604c22019-02-13 14:11:29 +0100846 osmo_hexdump_nospc(at->vec.ck, sizeof(at->vec.ck)));
Harald Welte89837d42016-05-06 23:28:11 +0200847 }
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100848 }
849
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100850 llist_for_each_entry(pdp, &gsub->sgsn_data->pdp_list, list) {
Max34604c22019-02-13 14:11:29 +0100851 vty_out(vty, " PDP info: Id: %d, Type: 0x%04x, APN: '%s'",
852 pdp->context_id, pdp->pdp_type, pdp->apn_str);
853
854 if (pdp->qos_subscribed_len)
855 vty_out(vty, " QoS: %s", osmo_hexdump(pdp->qos_subscribed, pdp->qos_subscribed_len));
856
857 vty_out(vty, "%s", VTY_NEWLINE);
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100858 }
859
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100860#if 0
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100861 /* print the expiration time of a subscriber */
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100862 if (gsub->expire_lu) {
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100863 strftime(expire_time, sizeof(expire_time),
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100864 "%a, %d %b %Y %T %z", localtime(&gsub->expire_lu));
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100865 expire_time[sizeof(expire_time) - 1] = '\0';
866 vty_out(vty, " Expiration Time: %s%s", expire_time, VTY_NEWLINE);
867 }
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100868#endif
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100869
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100870 if (gsub->flags)
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100871 vty_out(vty, " Flags: %s%s%s%s%s%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100872 gsub->flags & GPRS_SUBSCRIBER_FIRST_CONTACT ?
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100873 "FIRST_CONTACT " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100874 gsub->flags & GPRS_SUBSCRIBER_CANCELLED ?
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100875 "CANCELLED " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100876 gsub->flags & GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING ?
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100877 "UPDATE_LOCATION_PENDING " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100878 gsub->flags & GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING ?
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100879 "AUTH_INFO_PENDING " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100880 gsub->flags & GPRS_SUBSCRIBER_ENABLE_PURGE ?
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100881 "ENABLE_PURGE " : "",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100882 VTY_NEWLINE);
883
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100884 vty_out(vty, " Use count: %u%s", gsub->use_count, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100885}
886
Neels Hofmeyr1a9414b2018-09-24 18:14:29 +0200887#define RESET_SGSN_STATE_STR \
888 "Remove all known subscribers, MM contexts and flush BSSGP queues." \
889 " Useful only when running tests against the SGSN\n"
890
Alexander Couzensc503f0a2018-08-07 17:50:04 +0200891DEFUN_HIDDEN(reset_sgsn_state,
892 reset_sgsn_state_cmd,
893 "reset sgsn state",
Neels Hofmeyr1a9414b2018-09-24 18:14:29 +0200894 RESET_SGSN_STATE_STR RESET_SGSN_STATE_STR RESET_SGSN_STATE_STR)
Alexander Couzensc503f0a2018-08-07 17:50:04 +0200895{
896 struct gprs_subscr *subscr, *tmp_subscr;
897 struct sgsn_mm_ctx *mm, *tmp_mm;
898
899 llist_for_each_entry_safe(mm, tmp_mm, &sgsn_mm_ctxts, list)
900 {
901 gsm0408_gprs_access_cancelled(mm, SGSN_ERROR_CAUSE_NONE);
902 }
903 vty_out(vty, "Cancelled MM Ctx. %s", VTY_NEWLINE);
904
905 llist_for_each_entry_safe(subscr, tmp_subscr, gprs_subscribers, entry) {
906 gprs_subscr_get(subscr);
907 gprs_subscr_cancel(subscr);
908 gprs_subscr_put(subscr);
909 }
910 vty_out(vty, "Removed all gprs subscribers.%s", VTY_NEWLINE);
911
912 bssgp_flush_all_queues();
913 vty_out(vty, "Flushed all BSSGPs queues.%s", VTY_NEWLINE);
914
Alexander Couzens35c34942018-09-17 04:39:14 +0200915 gtp_clear_queues(sgsn->gsn);
Alexander Couzensa66f0f22018-09-18 16:09:18 +0200916 vty_out(vty, "Flushed rx & tx queus towards the GGSN.%s", VTY_NEWLINE);
Alexander Couzens35c34942018-09-17 04:39:14 +0200917
Alexander Couzensc503f0a2018-08-07 17:50:04 +0200918 /* remove all queues to bssgp */
919 return CMD_SUCCESS;
920}
921
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100922DEFUN(show_subscr_cache,
923 show_subscr_cache_cmd,
924 "show subscriber cache",
925 SHOW_STR "Show information about subscribers\n"
926 "Display contents of subscriber cache\n")
927{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100928 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100929
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100930 llist_for_each_entry(subscr, gprs_subscribers, entry) {
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100931 vty_out(vty, " Subscriber:%s", VTY_NEWLINE);
932 subscr_dump_full_vty(vty, subscr, 0);
933 }
934
935 return CMD_SUCCESS;
936}
937
938#define UPDATE_SUBSCR_STR "update-subscriber imsi IMSI "
939#define UPDATE_SUBSCR_HELP "Update subscriber list\n" \
940 "Use the IMSI to select the subscriber\n" \
941 "The IMSI\n"
942
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100943#define UPDATE_SUBSCR_INSERT_HELP "Insert data into the subscriber record\n"
944
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100945DEFUN(update_subscr_insert_auth_triplet, update_subscr_insert_auth_triplet_cmd,
946 UPDATE_SUBSCR_STR "insert auth-triplet <1-5> sres SRES rand RAND kc KC",
947 UPDATE_SUBSCR_HELP
948 UPDATE_SUBSCR_INSERT_HELP
949 "Update authentication triplet\n"
950 "Triplet index\n"
951 "Set SRES value\nSRES value (4 byte) in hex\n"
952 "Set RAND value\nRAND value (16 byte) in hex\n"
953 "Set Kc value\nKc value (8 byte) in hex\n")
954{
955 const char *imsi = argv[0];
956 const int cksn = atoi(argv[1]) - 1;
957 const char *sres_str = argv[2];
958 const char *rand_str = argv[3];
959 const char *kc_str = argv[4];
960 struct gsm_auth_tuple at = {0,};
961
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100962 struct gprs_subscr *subscr;
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100963
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100964 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100965 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100966 vty_out(vty, "%% unable get subscriber record for %s%s",
967 imsi, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100968 return CMD_WARNING;
969 }
970
971 OSMO_ASSERT(subscr->sgsn_data);
972
Harald Welte121e9a42016-04-20 13:13:19 +0200973 if (osmo_hexparse(sres_str, &at.vec.sres[0], sizeof(at.vec.sres)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100974 vty_out(vty, "%% invalid SRES value '%s'%s",
975 sres_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100976 goto failed;
977 }
Harald Welte121e9a42016-04-20 13:13:19 +0200978 if (osmo_hexparse(rand_str, &at.vec.rand[0], sizeof(at.vec.rand)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100979 vty_out(vty, "%% invalid RAND value '%s'%s",
980 rand_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100981 goto failed;
982 }
Harald Welte121e9a42016-04-20 13:13:19 +0200983 if (osmo_hexparse(kc_str, &at.vec.kc[0], sizeof(at.vec.kc)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100984 vty_out(vty, "%% invalid Kc value '%s'%s",
985 kc_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100986 goto failed;
987 }
988 at.key_seq = cksn;
989
990 subscr->sgsn_data->auth_triplets[cksn] = at;
991 subscr->sgsn_data->auth_triplets_updated = 1;
992
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100993 gprs_subscr_put(subscr);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100994
995 return CMD_SUCCESS;
996
997failed:
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100998 gprs_subscr_put(subscr);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100999 return CMD_SUCCESS;
1000}
1001
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001002DEFUN(update_subscr_cancel, update_subscr_cancel_cmd,
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +01001003 UPDATE_SUBSCR_STR "cancel (update-procedure|subscription-withdraw)",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001004 UPDATE_SUBSCR_HELP
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +01001005 "Cancel (remove) subscriber record\n"
1006 "The MS moved to another SGSN\n"
1007 "The subscription is no longer valid\n")
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001008{
1009 const char *imsi = argv[0];
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +01001010 const char *cancel_type = argv[1];
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001011
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001012 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001013
1014 subscr = gprs_subscr_get_by_imsi(imsi);
1015 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +01001016 vty_out(vty, "%% no subscriber record for %s%s",
1017 imsi, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001018 return CMD_WARNING;
1019 }
1020
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +01001021 if (strcmp(cancel_type, "update-procedure") == 0)
1022 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
1023 else
1024 subscr->sgsn_data->error_cause = GMM_CAUSE_IMPL_DETACHED;
1025
Jacob Erlbeck37139e52015-01-23 13:52:55 +01001026 gprs_subscr_cancel(subscr);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001027 gprs_subscr_put(subscr);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001028
1029 return CMD_SUCCESS;
1030}
1031
Jacob Erlbeckd9193432015-01-19 14:11:46 +01001032DEFUN(update_subscr_create, update_subscr_create_cmd,
1033 UPDATE_SUBSCR_STR "create",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001034 UPDATE_SUBSCR_HELP
Jacob Erlbeckd9193432015-01-19 14:11:46 +01001035 "Create a subscriber entry\n")
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001036{
1037 const char *imsi = argv[0];
1038
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001039 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001040
1041 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +01001042 if (subscr) {
1043 vty_out(vty, "%% subscriber record already exists for %s%s",
1044 imsi, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001045 return CMD_WARNING;
1046 }
1047
Jacob Erlbeckd9193432015-01-19 14:11:46 +01001048 subscr = gprs_subscr_get_or_create(imsi);
Alexander Couzens3326ba72020-12-09 22:02:55 +01001049 if (!subscr) {
1050 vty_out(vty, "Can not create subscriber. Out of memory.%s", imsi);
1051 return CMD_WARNING;
1052 }
Jacob Erlbeckd9193432015-01-19 14:11:46 +01001053 subscr->keep_in_ram = 1;
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001054 gprs_subscr_put(subscr);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001055
1056 return CMD_SUCCESS;
1057}
1058
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001059DEFUN(update_subscr_destroy, update_subscr_destroy_cmd,
1060 UPDATE_SUBSCR_STR "destroy",
1061 UPDATE_SUBSCR_HELP
1062 "Destroy a subscriber entry\n")
1063{
1064 const char *imsi = argv[0];
1065
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001066 struct gprs_subscr *subscr;
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001067
1068 subscr = gprs_subscr_get_by_imsi(imsi);
1069 if (!subscr) {
1070 vty_out(vty, "%% subscriber record does not exist for %s%s",
1071 imsi, VTY_NEWLINE);
1072 return CMD_WARNING;
1073 }
1074
1075 subscr->keep_in_ram = 0;
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +01001076 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001077 gprs_subscr_cancel(subscr);
1078 if (subscr->use_count > 1)
1079 vty_out(vty, "%% subscriber is still in use%s",
1080 VTY_NEWLINE);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001081 gprs_subscr_put(subscr);
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001082
1083 return CMD_SUCCESS;
1084}
1085
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001086#define UL_ERR_STR "system-failure|data-missing|unexpected-data-value|" \
1087 "unknown-subscriber|roaming-not-allowed"
1088
1089#define UL_ERR_HELP \
1090 "Force error code SystemFailure\n" \
1091 "Force error code DataMissing\n" \
1092 "Force error code UnexpectedDataValue\n" \
1093 "Force error code UnknownSubscriber\n" \
1094 "Force error code RoamingNotAllowed\n"
1095
1096DEFUN(update_subscr_update_location_result, update_subscr_update_location_result_cmd,
1097 UPDATE_SUBSCR_STR "update-location-result (ok|" UL_ERR_STR ")",
1098 UPDATE_SUBSCR_HELP
1099 "Complete the update location procedure\n"
1100 "The update location request succeeded\n"
1101 UL_ERR_HELP)
1102{
1103 const char *imsi = argv[0];
1104 const char *ret_code_str = argv[1];
1105
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001106 struct gprs_subscr *subscr;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001107
Jacob Erlbeckd6267d12015-01-19 11:10:04 +01001108 const struct value_string cause_mapping[] = {
1109 { GMM_CAUSE_NET_FAIL, "system-failure" },
1110 { GMM_CAUSE_INV_MAND_INFO, "data-missing" },
1111 { GMM_CAUSE_PROTO_ERR_UNSPEC, "unexpected-data-value" },
1112 { GMM_CAUSE_IMSI_UNKNOWN, "unknown-subscriber" },
1113 { GMM_CAUSE_GPRS_NOTALLOWED, "roaming-not-allowed" },
1114 { 0, NULL }
1115 };
1116
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001117 subscr = gprs_subscr_get_by_imsi(imsi);
1118 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +01001119 vty_out(vty, "%% unable to get subscriber record for %s%s",
1120 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001121 return CMD_WARNING;
1122 }
Jacob Erlbeckd6267d12015-01-19 11:10:04 +01001123
1124 if (strcmp(ret_code_str, "ok") == 0) {
1125 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001126 subscr->authorized = 1;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +01001127 } else {
1128 subscr->sgsn_data->error_cause =
1129 get_string_value(cause_mapping, ret_code_str);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001130 subscr->authorized = 0;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +01001131 }
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001132
1133 gprs_subscr_update(subscr);
1134
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001135 gprs_subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001136
1137 return CMD_SUCCESS;
1138}
1139
1140DEFUN(update_subscr_update_auth_info, update_subscr_update_auth_info_cmd,
1141 UPDATE_SUBSCR_STR "update-auth-info",
1142 UPDATE_SUBSCR_HELP
1143 "Complete the send authentication info procedure\n")
1144{
1145 const char *imsi = argv[0];
1146
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001147 struct gprs_subscr *subscr;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001148
1149 subscr = gprs_subscr_get_by_imsi(imsi);
1150 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +01001151 vty_out(vty, "%% unable to get subscriber record for %s%s",
1152 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001153 return CMD_WARNING;
1154 }
1155
1156 gprs_subscr_update_auth_info(subscr);
1157
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001158 gprs_subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001159
1160 return CMD_SUCCESS;
1161}
1162
Stefan Sperling88220092018-12-11 14:42:00 +01001163DEFUN(cfg_gsup_ipa_name,
1164 cfg_gsup_ipa_name_cmd,
1165 "gsup ipa-name NAME",
1166 "GSUP Parameters\n"
1167 "Set the IPA name of this SGSN\n"
1168 "A unique name for this SGSN. For example: PLMN + redundancy server number: SGSN-901-70-0. "
1169 "This name is used for GSUP routing and must be set if more than one SGSN is connected to the network. "
1170 "The default is 'SGSN-00-00-00-00-00-00'.\n")
1171{
1172 if (vty->type != VTY_FILE) {
1173 vty_out(vty, "The IPA name cannot be changed at run-time; "
1174 "It can only be set in the configuraton file.%s", VTY_NEWLINE);
1175 return CMD_WARNING;
1176 }
1177
1178 g_cfg->sgsn_ipa_name = talloc_strdup(tall_vty_ctx, argv[0]);
1179 return CMD_SUCCESS;
1180}
1181
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001182DEFUN(cfg_gsup_remote_ip, cfg_gsup_remote_ip_cmd,
1183 "gsup remote-ip A.B.C.D",
1184 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001185 "Set the IP address of the remote GSUP server (e.g. OsmoHLR)."
1186 " This setting only applies if 'auth-policy remote' is used.\n"
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001187 "IPv4 Address\n")
1188{
1189 inet_aton(argv[0], &g_cfg->gsup_server_addr.sin_addr);
1190
1191 return CMD_SUCCESS;
1192}
1193
1194DEFUN(cfg_gsup_remote_port, cfg_gsup_remote_port_cmd,
1195 "gsup remote-port <0-65535>",
1196 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001197 "Set the TCP port of the remote GSUP server, see also 'gsup remote-ip'\n"
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001198 "Remote TCP port\n")
1199{
1200 g_cfg->gsup_server_port = atoi(argv[0]);
1201
1202 return CMD_SUCCESS;
1203}
1204
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001205DEFUN(cfg_gsup_oap_id, cfg_gsup_oap_id_cmd,
1206 "gsup oap-id <0-65535>",
1207 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001208 "Set the OAP client ID for authentication on the GSUP protocol."
1209 " This setting only applies if 'auth-policy remote' is used.\n"
1210 "OAP client ID (0 == disabled)\n")
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001211{
1212 /* VTY ensures range */
1213 g_cfg->oap.client_id = (uint16_t)atoi(argv[0]);
1214 return CMD_SUCCESS;
1215}
1216
1217DEFUN(cfg_gsup_oap_k, cfg_gsup_oap_k_cmd,
1218 "gsup oap-k K",
1219 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001220 "Set the OAP shared secret key K for authentication on the GSUP protocol."
1221 " This setting only applies if auth-policy remote is used.\n"
1222 "K value (16 byte) hex\n")
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001223{
1224 const char *k = argv[0];
1225
1226 g_cfg->oap.secret_k_present = 0;
1227
1228 if ((!k) || (strlen(k) == 0))
1229 goto disable;
1230
1231 int k_len = osmo_hexparse(k,
1232 g_cfg->oap.secret_k,
1233 sizeof(g_cfg->oap.secret_k));
1234 if (k_len != 16) {
1235 vty_out(vty, "%% need exactly 16 octets for oap-k, got %d.%s",
1236 k_len, VTY_NEWLINE);
1237 goto disable;
1238 }
1239
1240 g_cfg->oap.secret_k_present = 1;
1241 return CMD_SUCCESS;
1242
1243disable:
1244 if (g_cfg->oap.client_id > 0) {
1245 vty_out(vty, "%% OAP client ID set, but invalid oap-k value disables OAP.%s",
1246 VTY_NEWLINE);
1247 return CMD_WARNING;
1248 }
1249 return CMD_SUCCESS;
1250}
1251
1252DEFUN(cfg_gsup_oap_opc, cfg_gsup_oap_opc_cmd,
1253 "gsup oap-opc OPC",
1254 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001255 "Set the OAP shared secret OPC for authentication on the GSUP protocol."
1256 " This setting only applies if auth-policy remote is used.\n"
1257 "OPC value (16 byte) hex\n")
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001258{
1259 const char *opc = argv[0];
1260
1261 g_cfg->oap.secret_opc_present = 0;
1262
1263 if ((!opc) || (strlen(opc) == 0))
1264 goto disable;
1265
1266 int opc_len = osmo_hexparse(opc,
1267 g_cfg->oap.secret_opc,
1268 sizeof(g_cfg->oap.secret_opc));
1269 if (opc_len != 16) {
1270 vty_out(vty, "%% need exactly 16 octets for oap-opc, got %d.%s",
1271 opc_len, VTY_NEWLINE);
1272 goto disable;
1273 }
1274
1275 g_cfg->oap.secret_opc_present = 1;
1276 return CMD_SUCCESS;
1277
1278disable:
1279 if (g_cfg->oap.client_id > 0) {
1280 vty_out(vty, "%% OAP client ID set, but invalid oap-opc value disables OAP.%s",
1281 VTY_NEWLINE);
1282 return CMD_WARNING;
1283 }
1284 return CMD_SUCCESS;
1285}
1286
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001287DEFUN(cfg_apn_name, cfg_apn_name_cmd,
1288 "access-point-name NAME",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001289 "Globally allow the given APN name for all subscribers.\n"
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001290 "Add this NAME to the list\n")
1291{
1292 return add_apn_ggsn_mapping(vty, argv[0], "", 0);
1293}
1294
1295DEFUN(cfg_no_apn_name, cfg_no_apn_name_cmd,
1296 "no access-point-name NAME",
1297 NO_STR "Configure a global list of allowed APNs\n"
1298 "Remove entry with NAME\n")
1299{
1300 struct apn_ctx *apn_ctx = sgsn_apn_ctx_by_name(argv[0], "");
1301 if (!apn_ctx)
1302 return CMD_SUCCESS;
1303
1304 sgsn_apn_ctx_free(apn_ctx);
1305 return CMD_SUCCESS;
1306}
1307
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001308DEFUN(cfg_cdr_filename, cfg_cdr_filename_cmd,
1309 "cdr filename NAME",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001310 "CDR\n"
1311 "Set the file name for the call-data-record file, logging the data usage of each subscriber.\n"
1312 "filename\n")
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001313{
1314 talloc_free(g_cfg->cdr.filename);
1315 g_cfg->cdr.filename = talloc_strdup(tall_vty_ctx, argv[0]);
1316 return CMD_SUCCESS;
1317}
1318
1319DEFUN(cfg_no_cdr_filename, cfg_no_cdr_filename_cmd,
1320 "no cdr filename",
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +01001321 NO_STR "CDR\nDisable saving CDR to file\n")
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001322{
1323 talloc_free(g_cfg->cdr.filename);
1324 g_cfg->cdr.filename = NULL;
1325 return CMD_SUCCESS;
1326}
1327
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +01001328DEFUN(cfg_cdr_trap, cfg_cdr_trap_cmd,
1329 "cdr trap",
1330 "CDR\nEnable sending CDR via TRAP CTRL messages\n")
1331{
1332 g_cfg->cdr.trap = true;
1333 return CMD_SUCCESS;
1334}
1335
1336DEFUN(cfg_no_cdr_trap, cfg_no_cdr_trap_cmd,
1337 "no cdr trap",
1338 NO_STR "CDR\nDisable sending CDR via TRAP CTRL messages\n")
1339{
1340 g_cfg->cdr.trap = false;
1341 return CMD_SUCCESS;
1342}
1343
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001344DEFUN(cfg_cdr_interval, cfg_cdr_interval_cmd,
1345 "cdr interval <1-2147483647>",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001346 "CDR\n"
1347 "Set the interval for the call-data-record file\n"
1348 "interval in seconds\n")
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001349{
1350 g_cfg->cdr.interval = atoi(argv[0]);
1351 return CMD_SUCCESS;
1352}
1353
Philippf1f34362016-08-26 17:00:21 +02001354#define COMPRESSION_STR "Configure compression\n"
1355DEFUN(cfg_no_comp_rfc1144, cfg_no_comp_rfc1144_cmd,
1356 "no compression rfc1144",
1357 NO_STR COMPRESSION_STR "disable rfc1144 TCP/IP header compression\n")
1358{
1359 g_cfg->pcomp_rfc1144.active = 0;
1360 g_cfg->pcomp_rfc1144.passive = 0;
1361 return CMD_SUCCESS;
1362}
1363
1364DEFUN(cfg_comp_rfc1144, cfg_comp_rfc1144_cmd,
1365 "compression rfc1144 active slots <1-256>",
1366 COMPRESSION_STR
Ruben Undheim55fcf112018-09-25 22:59:34 +02001367 "RFC1144 Header compression scheme\n"
Philippf1f34362016-08-26 17:00:21 +02001368 "Compression is actively proposed\n"
1369 "Number of compression state slots\n"
1370 "Number of compression state slots\n")
1371{
1372 g_cfg->pcomp_rfc1144.active = 1;
1373 g_cfg->pcomp_rfc1144.passive = 1;
1374 g_cfg->pcomp_rfc1144.s01 = atoi(argv[0]) - 1;
1375 return CMD_SUCCESS;
1376}
1377
1378DEFUN(cfg_comp_rfc1144p, cfg_comp_rfc1144p_cmd,
1379 "compression rfc1144 passive",
1380 COMPRESSION_STR
Ruben Undheim55fcf112018-09-25 22:59:34 +02001381 "RFC1144 Header compression scheme\n"
Philippf1f34362016-08-26 17:00:21 +02001382 "Compression is available on request\n")
1383{
1384 g_cfg->pcomp_rfc1144.active = 0;
1385 g_cfg->pcomp_rfc1144.passive = 1;
1386 return CMD_SUCCESS;
1387}
1388
Philipp73f83d52016-09-02 13:38:01 +02001389DEFUN(cfg_no_comp_v42bis, cfg_no_comp_v42bis_cmd,
1390 "no compression v42bis",
1391 NO_STR COMPRESSION_STR "disable V.42bis data compression\n")
1392{
1393 g_cfg->dcomp_v42bis.active = 0;
1394 g_cfg->dcomp_v42bis.passive = 0;
1395 return CMD_SUCCESS;
1396}
1397
1398DEFUN(cfg_comp_v42bis, cfg_comp_v42bis_cmd,
1399 "compression v42bis active direction (ms|sgsn|both) codewords <512-65535> strlen <6-250>",
1400 COMPRESSION_STR
Ruben Undheim55fcf112018-09-25 22:59:34 +02001401 "V.42bis data compression scheme\n"
Philipp73f83d52016-09-02 13:38:01 +02001402 "Compression is actively proposed\n"
1403 "Direction in which the compression shall be active (p0)\n"
1404 "Compress ms->sgsn direction only\n"
1405 "Compress sgsn->ms direction only\n"
1406 "Both directions\n"
1407 "Number of codewords (p1)\n"
1408 "Number of codewords\n"
1409 "Maximum string length (p2)\n" "Maximum string length\n")
1410{
1411 g_cfg->dcomp_v42bis.active = 1;
1412 g_cfg->dcomp_v42bis.passive = 1;
1413
1414 switch (argv[0][0]) {
1415 case 'm':
1416 g_cfg->dcomp_v42bis.p0 = 1;
1417 break;
1418 case 's':
1419 g_cfg->dcomp_v42bis.p0 = 2;
1420 break;
1421 case 'b':
1422 g_cfg->dcomp_v42bis.p0 = 3;
1423 break;
1424 }
1425
1426 g_cfg->dcomp_v42bis.p1 = atoi(argv[1]);
1427 g_cfg->dcomp_v42bis.p2 = atoi(argv[2]);
1428 return CMD_SUCCESS;
1429}
1430
1431DEFUN(cfg_comp_v42bisp, cfg_comp_v42bisp_cmd,
1432 "compression v42bis passive",
1433 COMPRESSION_STR
Ruben Undheim55fcf112018-09-25 22:59:34 +02001434 "V.42bis data compression scheme\n"
Philipp73f83d52016-09-02 13:38:01 +02001435 "Compression is available on request\n")
1436{
1437 g_cfg->dcomp_v42bis.active = 0;
1438 g_cfg->dcomp_v42bis.passive = 1;
1439 return CMD_SUCCESS;
1440}
1441
Pau Espin Pedrol2c908992019-08-19 19:06:06 +02001442#if BUILD_IU
1443DEFUN(cfg_sgsn_cs7_instance_iu,
1444 cfg_sgsn_cs7_instance_iu_cmd,
1445 "cs7-instance-iu <0-15>",
1446 "Set SS7 to be used by the Iu-Interface.\n" "SS7 instance reference number (default: 0)\n")
1447{
1448 g_cfg->iu.cs7_instance = atoi(argv[0]);
1449 return CMD_SUCCESS;
1450}
1451#endif
1452
Pau Espin Pedrole5c89982021-05-03 18:16:42 +02001453DEFUN(cfg_sgsn_mme, cfg_sgsn_mme_cmd,
1454 "mme NAME",
1455 "Configure an MME peer\n"
1456 "Name identifying the MME peer\n")
1457{
1458 struct sgsn_mme_ctx *mme;
1459
1460 mme = sgsn_mme_ctx_find_alloc(sgsn, argv[0]);
1461 if (!mme)
1462 return CMD_WARNING;
1463
1464 vty->node = MME_NODE;
1465 vty->index = mme;
1466
1467 return CMD_SUCCESS;
1468}
1469
1470DEFUN(cfg_sgsn_no_mme, cfg_sgsn_no_mme_cmd,
1471 "no mme NAME",
1472 NO_STR "Delete an MME peer configuration\n"
1473 "Name identifying the MME peer\n")
1474{
1475 struct sgsn_mme_ctx *mme;
1476
1477 mme = sgsn_mme_ctx_by_name(sgsn, argv[0]);
1478 if (!mme) {
1479 vty_out(vty, "%% MME %s doesn't exist.%s",
1480 argv[0], VTY_NEWLINE);
1481 return CMD_WARNING;
1482 }
1483
1484 sgsn_mme_ctx_free(mme);
1485
1486 return CMD_SUCCESS;
1487}
1488
1489#define GTP_STR "Configure GTP connection\n"
1490
1491DEFUN(cfg_mme_remote_ip, cfg_mme_remote_ip_cmd,
1492 "gtp remote-ip A.B.C.D",
1493 GTP_STR "Set Remote GTP IP address\n" IP_STR)
1494{
1495 struct sgsn_mme_ctx *mme = (struct sgsn_mme_ctx *) vty->index;
1496
1497 inet_aton(argv[0], &mme->remote_addr);
1498
1499 return CMD_SUCCESS;
1500}
1501
1502#define RAN_INFO_STR "Configure RAN Information Relay routing\n"
1503#define TAI_DOC "MCC\n" "MNC\n" "TAC\n"
1504
1505DEFUN(cfg_mme_ran_info_relay_tai, cfg_mme_ran_info_relay_tai_cmd,
1506 "gtp ran-info-relay <0-999> <0-999> <0-65535>",
1507 GTP_STR RAN_INFO_STR TAI_DOC)
1508{
1509 struct sgsn_mme_ctx *mme = (struct sgsn_mme_ctx *) vty->index;
1510 struct sgsn_mme_ctx *mme_tmp;
1511 struct osmo_eutran_tai tai;
1512
1513 const char *mcc = argv[0];
1514 const char *mnc = argv[1];
1515 const char *tac = argv[2];
1516
1517 if (osmo_mcc_from_str(mcc, &tai.mcc)) {
1518 vty_out(vty, "%% Error decoding MCC: %s%s", mcc, VTY_NEWLINE);
1519 return CMD_WARNING;
1520 }
1521 if (osmo_mnc_from_str(mnc, &tai.mnc, &tai.mnc_3_digits)) {
1522 vty_out(vty, "%% Error decoding MNC: %s%s", mnc, VTY_NEWLINE);
1523 return CMD_WARNING;
1524 }
1525 tai.tac = atoi(tac);
1526
1527 if ((mme_tmp = sgsn_mme_ctx_by_route(sgsn, &tai))) {
1528 if (mme_tmp != mme) {
1529 vty_out(vty, "%% Another MME %s already contains this route%s",
1530 mme_tmp->name, VTY_NEWLINE);
1531 return CMD_WARNING;
1532 }
1533 /* else: NO-OP, return */
1534 return CMD_SUCCESS;
1535 }
1536
1537 sgsn_mme_ctx_route_add(mme, &tai);
1538 return CMD_SUCCESS;
1539}
1540
1541DEFUN(cfg_mme_no_ran_info_relay_tai, cfg_mme_no_ran_info_relay_tai_cmd,
1542 "no gtp ran-info-relay <0-999> <0-999> <0-65535>",
1543 NO_STR GTP_STR RAN_INFO_STR TAI_DOC)
1544{
1545 struct sgsn_mme_ctx *mme = (struct sgsn_mme_ctx *) vty->index;
1546 struct sgsn_mme_ctx *mme_tmp;
1547 struct osmo_eutran_tai tai;
1548
1549 const char *mcc = argv[0];
1550 const char *mnc = argv[1];
1551 const char *tac = argv[2];
1552
1553 if (osmo_mcc_from_str(mcc, &tai.mcc)) {
1554 vty_out(vty, "%% Error decoding MCC: %s%s", mcc, VTY_NEWLINE);
1555 return CMD_WARNING;
1556 }
1557 if (osmo_mnc_from_str(mnc, &tai.mnc, &tai.mnc_3_digits)) {
1558 vty_out(vty, "%% Error decoding MNC: %s%s", mnc, VTY_NEWLINE);
1559 return CMD_WARNING;
1560 }
1561 tai.tac = atoi(tac);
1562
1563 if ((mme_tmp = sgsn_mme_ctx_by_route(sgsn, &tai))) {
1564 if (mme_tmp != mme) {
1565 vty_out(vty, "%% Another MME %s contains this route%s",
1566 mme_tmp->name, VTY_NEWLINE);
1567 return CMD_WARNING;
1568 }
1569 sgsn_mme_ctx_route_del(mme, &tai);
1570 return CMD_SUCCESS;
1571 } else {
1572 vty_out(vty, "%% This route doesn't exist in current MME %s%s",
1573 mme->name, VTY_NEWLINE);
1574 return CMD_WARNING;
1575 }
1576}
1577
1578DEFUN(cfg_mme_ran_info_relay_default, cfg_mme_ran_info_relay_default_cmd,
1579 "gtp ran-info-relay default",
1580 GTP_STR RAN_INFO_STR "Set as default route")
1581{
1582 struct sgsn_mme_ctx *mme = (struct sgsn_mme_ctx *) vty->index;
1583 struct sgsn_mme_ctx *default_mme;
1584
1585 if (mme->default_route)
1586 return CMD_SUCCESS; /* NO-OP */
1587
1588 if ((default_mme = sgsn_mme_ctx_by_default_route(sgsn))) {
1589 vty_out(vty, "%% Another MME %s is already set as default route, "
1590 "remove it before setting it here.%s",
1591 default_mme->name, VTY_NEWLINE);
1592 return CMD_WARNING;
1593 }
1594
1595 mme->default_route = true;
1596 return CMD_SUCCESS;
1597}
1598
1599DEFUN(cfg_mme_no_ran_info_relay_default, cfg_mme_no_ran_info_relay_default_cmd,
1600 "no gtp ran-info-relay default",
1601 NO_STR GTP_STR RAN_INFO_STR "Set as default route")
1602{
1603 struct sgsn_mme_ctx *mme = (struct sgsn_mme_ctx *) vty->index;
1604 mme->default_route = false;
1605 return CMD_SUCCESS;
1606}
1607
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001608int sgsn_vty_init(struct sgsn_config *cfg)
Harald Welte288be162010-05-01 16:48:27 +02001609{
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001610 g_cfg = cfg;
1611
Pau Espin Pedrola299d652019-08-14 19:11:10 +02001612 g_cfg->T_defs = sgsn_T_defs;
1613 osmo_tdefs_reset(g_cfg->T_defs);
1614
Harald Welted193cb32010-05-17 22:58:03 +02001615 install_element_ve(&show_sgsn_cmd);
1616 //install_element_ve(&show_mmctx_tlli_cmd);
1617 install_element_ve(&show_mmctx_imsi_cmd);
1618 install_element_ve(&show_mmctx_all_cmd);
1619 install_element_ve(&show_pdpctx_all_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001620 install_element_ve(&show_subscr_cache_cmd);
Pau Espin Pedrola299d652019-08-14 19:11:10 +02001621 install_element_ve(&show_timer_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001622
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01001623 install_element(ENABLE_NODE, &update_subscr_insert_auth_triplet_cmd);
Jacob Erlbeckd9193432015-01-19 14:11:46 +01001624 install_element(ENABLE_NODE, &update_subscr_create_cmd);
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001625 install_element(ENABLE_NODE, &update_subscr_destroy_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001626 install_element(ENABLE_NODE, &update_subscr_cancel_cmd);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001627 install_element(ENABLE_NODE, &update_subscr_update_location_result_cmd);
1628 install_element(ENABLE_NODE, &update_subscr_update_auth_info_cmd);
Alexander Couzensc503f0a2018-08-07 17:50:04 +02001629 install_element(ENABLE_NODE, &reset_sgsn_state_cmd);
Harald Welte288be162010-05-01 16:48:27 +02001630
1631 install_element(CONFIG_NODE, &cfg_sgsn_cmd);
1632 install_node(&sgsn_node, config_write_sgsn);
Keithc70e8382020-10-19 22:24:48 +02001633 install_element(SGSN_NODE, &cfg_sgsn_state_dir_cmd);
Harald Weltee300d002010-06-02 12:41:34 +02001634 install_element(SGSN_NODE, &cfg_sgsn_bind_addr_cmd);
Harald Welted193cb32010-05-17 22:58:03 +02001635 install_element(SGSN_NODE, &cfg_ggsn_remote_ip_cmd);
1636 //install_element(SGSN_NODE, &cfg_ggsn_remote_port_cmd);
1637 install_element(SGSN_NODE, &cfg_ggsn_gtp_version_cmd);
Pau Espin Pedrolfa120102018-07-09 20:37:47 +02001638 install_element(SGSN_NODE, &cfg_ggsn_echo_interval_cmd);
Pau Espin Pedrola83850c2018-07-10 12:43:59 +02001639 install_element(SGSN_NODE, &cfg_ggsn_no_echo_interval_cmd);
Harald Welte7f6da482013-03-19 11:00:13 +01001640 install_element(SGSN_NODE, &cfg_imsi_acl_cmd);
Harald Welte3dfb5492013-03-19 11:48:54 +01001641 install_element(SGSN_NODE, &cfg_auth_policy_cmd);
Vadim Yanitskiy794f4462019-05-27 05:39:06 +07001642 install_element(SGSN_NODE, &cfg_authentication_cmd);
Max93408ae2016-06-28 14:10:16 +02001643 install_element(SGSN_NODE, &cfg_encrypt_cmd);
Stefan Sperling88220092018-12-11 14:42:00 +01001644 install_element(SGSN_NODE, &cfg_gsup_ipa_name_cmd);
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001645 install_element(SGSN_NODE, &cfg_gsup_remote_ip_cmd);
1646 install_element(SGSN_NODE, &cfg_gsup_remote_port_cmd);
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001647 install_element(SGSN_NODE, &cfg_gsup_oap_id_cmd);
1648 install_element(SGSN_NODE, &cfg_gsup_oap_k_cmd);
1649 install_element(SGSN_NODE, &cfg_gsup_oap_opc_cmd);
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +01001650 install_element(SGSN_NODE, &cfg_apn_ggsn_cmd);
1651 install_element(SGSN_NODE, &cfg_apn_imsi_ggsn_cmd);
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001652 install_element(SGSN_NODE, &cfg_apn_name_cmd);
1653 install_element(SGSN_NODE, &cfg_no_apn_name_cmd);
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001654 install_element(SGSN_NODE, &cfg_cdr_filename_cmd);
1655 install_element(SGSN_NODE, &cfg_no_cdr_filename_cmd);
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +01001656 install_element(SGSN_NODE, &cfg_cdr_trap_cmd);
1657 install_element(SGSN_NODE, &cfg_no_cdr_trap_cmd);
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001658 install_element(SGSN_NODE, &cfg_cdr_interval_cmd);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001659 install_element(SGSN_NODE, &cfg_ggsn_dynamic_lookup_cmd);
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +08001660 install_element(SGSN_NODE, &cfg_grx_ggsn_cmd);
Harald Welte288be162010-05-01 16:48:27 +02001661
Pau Espin Pedrola299d652019-08-14 19:11:10 +02001662 install_element(SGSN_NODE, &cfg_sgsn_timer_cmd);
Harald Welte94508822015-08-15 19:08:21 +02001663
Philippf1f34362016-08-26 17:00:21 +02001664 install_element(SGSN_NODE, &cfg_no_comp_rfc1144_cmd);
1665 install_element(SGSN_NODE, &cfg_comp_rfc1144_cmd);
1666 install_element(SGSN_NODE, &cfg_comp_rfc1144p_cmd);
Philipp73f83d52016-09-02 13:38:01 +02001667 install_element(SGSN_NODE, &cfg_no_comp_v42bis_cmd);
1668 install_element(SGSN_NODE, &cfg_comp_v42bis_cmd);
1669 install_element(SGSN_NODE, &cfg_comp_v42bisp_cmd);
Neels Hofmeyr2188a772016-05-20 21:59:55 +02001670
Pau Espin Pedrole5c89982021-05-03 18:16:42 +02001671 install_element(SGSN_NODE, &cfg_sgsn_mme_cmd);
1672 install_element(SGSN_NODE, &cfg_sgsn_no_mme_cmd);
1673 install_node(&mme_node, NULL);
1674 install_element(MME_NODE, &cfg_mme_remote_ip_cmd);
1675 install_element(MME_NODE, &cfg_mme_ran_info_relay_default_cmd);
1676 install_element(MME_NODE, &cfg_mme_no_ran_info_relay_default_cmd);
1677 install_element(MME_NODE, &cfg_mme_ran_info_relay_tai_cmd);
1678 install_element(MME_NODE, &cfg_mme_no_ran_info_relay_tai_cmd);
1679
Neels Hofmeyr2188a772016-05-20 21:59:55 +02001680#ifdef BUILD_IU
Pau Espin Pedrol2c908992019-08-19 19:06:06 +02001681 install_element(SGSN_NODE, &cfg_sgsn_cs7_instance_iu_cmd);
Neels Hofmeyra7a39472017-07-05 15:19:52 +02001682 ranap_iu_vty_init(SGSN_NODE, &g_cfg->iu.rab_assign_addr_enc);
Neels Hofmeyr2188a772016-05-20 21:59:55 +02001683#endif
Harald Welte288be162010-05-01 16:48:27 +02001684 return 0;
1685}
1686
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001687int sgsn_parse_config(const char *config_file)
Harald Welte288be162010-05-01 16:48:27 +02001688{
1689 int rc;
1690
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001691 /* make sure sgsn_vty_init() was called before this */
1692 OSMO_ASSERT(g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +01001693
Harald Weltedcccb182010-05-16 20:52:23 +02001694 rc = vty_read_config_file(config_file, NULL);
Harald Welte288be162010-05-01 16:48:27 +02001695 if (rc < 0) {
1696 fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
1697 return rc;
1698 }
1699
Neels Hofmeyr27355c92017-02-24 06:28:31 +01001700 if (g_cfg->auth_policy == SGSN_AUTH_POLICY_REMOTE
1701 && !(g_cfg->gsup_server_addr.sin_addr.s_addr
1702 && g_cfg->gsup_server_port)) {
1703 fprintf(stderr, "Configuration error:"
1704 " 'auth-policy remote' requires both"
1705 " 'gsup remote-ip' and 'gsup remote-port'\n");
1706 return -EINVAL;
1707 }
1708
Harald Welte288be162010-05-01 16:48:27 +02001709 return 0;
1710}