blob: 76d5202bf2ff802d0f150a0f2400b95e6c562c15 [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 }
657 vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
658 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;
666
667 llist_for_each_entry(mm, &sgsn_mm_ctxts, list)
668 vty_dump_mmctx(vty, "", mm, argv[0] ? 1 : 0);
669
670 return CMD_SUCCESS;
671}
672
Harald Welted193cb32010-05-17 22:58:03 +0200673DEFUN(show_pdpctx_all, show_pdpctx_all_cmd,
674 "show pdp-context all",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100675 SHOW_STR "Display information on PDP Context\n" "Show everything\n")
Harald Welted193cb32010-05-17 22:58:03 +0200676{
677 struct sgsn_pdp_ctx *pdp;
678
679 llist_for_each_entry(pdp, &sgsn_pdp_ctxts, g_list)
680 vty_dump_pdp(vty, "", pdp);
681
682 return CMD_SUCCESS;
683}
Harald Welte288be162010-05-01 16:48:27 +0200684
Harald Welte7f6da482013-03-19 11:00:13 +0100685
686DEFUN(imsi_acl, cfg_imsi_acl_cmd,
687 "imsi-acl (add|del) IMSI",
688 "Access Control List of foreign IMSIs\n"
689 "Add IMSI to ACL\n"
690 "Remove IMSI from ACL\n"
691 "IMSI of subscriber\n")
692{
Maxef38b4c2018-11-20 10:25:53 +0100693 char imsi_sanitized[GSM23003_IMSI_MAX_DIGITS + 1];
Harald Welte7f6da482013-03-19 11:00:13 +0100694 const char *op = argv[0];
Philipp Maier6ee49d82017-02-28 16:53:07 +0100695 const char *imsi = imsi_sanitized;
Maxf4fa6952018-01-15 12:12:51 +0100696 size_t len = strnlen(argv[1], GSM23003_IMSI_MAX_DIGITS + 1);
Harald Welte7f6da482013-03-19 11:00:13 +0100697 int rc;
698
Maxef38b4c2018-11-20 10:25:53 +0100699 memset(imsi_sanitized, '0', GSM23003_IMSI_MAX_DIGITS);
700 imsi_sanitized[GSM23003_IMSI_MAX_DIGITS] = '\0';
701
Philipp Maier6ee49d82017-02-28 16:53:07 +0100702 /* Sanitize IMSI */
Maxf4fa6952018-01-15 12:12:51 +0100703 if (len > GSM23003_IMSI_MAX_DIGITS) {
704 vty_out(vty, "%% IMSI (%s) too long (max %u digits) -- ignored!%s",
705 argv[1], GSM23003_IMSI_MAX_DIGITS, VTY_NEWLINE);
Philipp Maier6ee49d82017-02-28 16:53:07 +0100706 return CMD_WARNING;
707 }
Maxf4fa6952018-01-15 12:12:51 +0100708
709 osmo_strlcpy(imsi_sanitized + GSM23003_IMSI_MAX_DIGITS - len, argv[1],
710 sizeof(imsi_sanitized) - (GSM23003_IMSI_MAX_DIGITS - len));
Philipp Maier6ee49d82017-02-28 16:53:07 +0100711
Harald Welte7f6da482013-03-19 11:00:13 +0100712 if (!strcmp(op, "add"))
Jacob Erlbeck3b5d4072014-10-24 15:11:03 +0200713 rc = sgsn_acl_add(imsi, g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +0100714 else
Jacob Erlbeck3b5d4072014-10-24 15:11:03 +0200715 rc = sgsn_acl_del(imsi, g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +0100716
717 if (rc < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100718 vty_out(vty, "%% unable to %s ACL%s", op, VTY_NEWLINE);
Harald Welte7f6da482013-03-19 11:00:13 +0100719 return CMD_WARNING;
720 }
721
722 return CMD_SUCCESS;
723}
724
Max93408ae2016-06-28 14:10:16 +0200725DEFUN(cfg_encrypt, cfg_encrypt_cmd,
726 "encryption (GEA0|GEA1|GEA2|GEA3|GEA4)",
727 "Set encryption algorithm for SGSN\n"
728 "Use GEA0 (no encryption)\n"
729 "Use GEA1\nUse GEA2\nUse GEA3\nUse GEA4\n")
730{
Max93408ae2016-06-28 14:10:16 +0200731 enum gprs_ciph_algo c = get_string_value(gprs_cipher_names, argv[0]);
Max086067f2017-05-02 13:03:28 +0200732 if (c != GPRS_ALGO_GEA0) {
733 if (!gprs_cipher_supported(c)) {
734 vty_out(vty, "%% cipher %s is unsupported in current version%s", argv[0], VTY_NEWLINE);
735 return CMD_WARNING;
736 }
737
738 if (!g_cfg->require_authentication) {
739 vty_out(vty, "%% unable to use encryption %s without authentication: please adjust auth-policy%s",
740 argv[0], VTY_NEWLINE);
741 return CMD_WARNING;
742 }
Max93408ae2016-06-28 14:10:16 +0200743 }
744
745 g_cfg->cipher = c;
746
747 return CMD_SUCCESS;
748}
749
Vadim Yanitskiy794f4462019-05-27 05:39:06 +0700750DEFUN(cfg_authentication, cfg_authentication_cmd,
751 "authentication (optional|required)",
Pau Espin Pedrold1463bc2019-06-13 19:03:25 +0200752 "Whether to enforce MS authentication in GERAN (only with auth-policy remote)\n"
753 "Allow MS to attach via GERAN without authentication (default and only possible value for non-remote auth-policy)\n"
754 "Always require authentication (only available for auth-policy remote, default with that auth-policy)\n")
Vadim Yanitskiy794f4462019-05-27 05:39:06 +0700755{
756 int required = (argv[0][0] == 'r');
757
758 if (vty->type != VTY_FILE) {
759 if (g_cfg->auth_policy != SGSN_AUTH_POLICY_REMOTE && required) {
760 vty_out(vty, "%% Authentication is not possible without HLR, "
761 "consider setting 'auth-policy' to 'remote'%s",
762 VTY_NEWLINE);
763 return CMD_WARNING;
764 }
765 }
766
767 g_cfg->require_authentication = required;
768 return CMD_SUCCESS;
769}
770
Harald Welte3dfb5492013-03-19 11:48:54 +0100771DEFUN(cfg_auth_policy, cfg_auth_policy_cmd,
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100772 "auth-policy (accept-all|closed|acl-only|remote)",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100773 "Configure the Authorization policy of the SGSN. This setting determines which subscribers are"
774 " permitted to register to the network.\n"
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100775 "Accept all IMSIs (DANGEROUS)\n"
776 "Accept only home network subscribers or those in the ACL\n"
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100777 "Accept only subscribers in the ACL\n"
778 "Use remote subscription data only (HLR)\n")
Harald Welte3dfb5492013-03-19 11:48:54 +0100779{
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100780 int val = get_string_value(sgsn_auth_pol_strs, argv[0]);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100781 OSMO_ASSERT(val >= SGSN_AUTH_POLICY_OPEN && val <= SGSN_AUTH_POLICY_REMOTE);
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100782 g_cfg->auth_policy = val;
Jacob Erlbeck771573c2014-12-19 18:08:48 +0100783 g_cfg->require_update_location = (val == SGSN_AUTH_POLICY_REMOTE);
Harald Welte3dfb5492013-03-19 11:48:54 +0100784
785 return CMD_SUCCESS;
786}
787
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100788/* Subscriber */
Neels Hofmeyr396f2e62017-09-04 15:13:25 +0200789#include <osmocom/sgsn/gprs_subscriber.h>
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100790
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100791static void subscr_dump_full_vty(struct vty *vty, struct gprs_subscr *gsub, int pending)
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100792{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100793#if 0
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100794 char expire_time[200];
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100795#endif
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100796 struct gsm_auth_tuple *at;
797 int at_idx;
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100798 struct sgsn_subscriber_pdp_data *pdp;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100799
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100800 vty_out(vty, " Authorized: %d%s",
801 gsub->authorized, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100802 vty_out(vty, " LAC: %d/0x%x%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100803 gsub->lac, gsub->lac, VTY_NEWLINE);
804 vty_out(vty, " IMSI: %s%s", gsub->imsi, VTY_NEWLINE);
805 if (gsub->tmsi != GSM_RESERVED_TMSI)
806 vty_out(vty, " TMSI: %08X%s", gsub->tmsi,
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100807 VTY_NEWLINE);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100808 if (gsub->sgsn_data->msisdn_len > 0)
Holger Hans Peter Freytherf7b38262015-04-23 16:58:33 -0400809 vty_out(vty, " MSISDN (BCD): %s%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100810 osmo_hexdump(gsub->sgsn_data->msisdn,
811 gsub->sgsn_data->msisdn_len),
Holger Hans Peter Freytherf7b38262015-04-23 16:58:33 -0400812 VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100813
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100814 if (strlen(gsub->imei) > 0)
815 vty_out(vty, " IMEI: %s%s", gsub->imei, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100816
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100817 for (at_idx = 0; at_idx < ARRAY_SIZE(gsub->sgsn_data->auth_triplets);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100818 at_idx++) {
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100819 at = &gsub->sgsn_data->auth_triplets[at_idx];
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100820 if (at->key_seq == GSM_KEY_SEQ_INVAL)
821 continue;
822
823 vty_out(vty, " A3A8 tuple (used %d times): ",
824 at->use_count);
Harald Welte89837d42016-05-06 23:28:11 +0200825 vty_out(vty, " CKSN: %d, ",
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100826 at->key_seq);
Harald Welte89837d42016-05-06 23:28:11 +0200827 if (at->vec.auth_types & OSMO_AUTH_TYPE_GSM) {
828 vty_out(vty, "RAND: %s, ",
Max34604c22019-02-13 14:11:29 +0100829 osmo_hexdump_nospc(at->vec.rand,
Harald Welte89837d42016-05-06 23:28:11 +0200830 sizeof(at->vec.rand)));
831 vty_out(vty, "SRES: %s, ",
Max34604c22019-02-13 14:11:29 +0100832 osmo_hexdump_nospc(at->vec.sres,
Harald Welte89837d42016-05-06 23:28:11 +0200833 sizeof(at->vec.sres)));
834 vty_out(vty, "Kc: %s%s",
Max34604c22019-02-13 14:11:29 +0100835 osmo_hexdump_nospc(at->vec.kc,
Harald Welte89837d42016-05-06 23:28:11 +0200836 sizeof(at->vec.kc)), VTY_NEWLINE);
837 }
838 if (at->vec.auth_types & OSMO_AUTH_TYPE_UMTS) {
839 vty_out(vty, " AUTN: %s, ",
840 osmo_hexdump(at->vec.autn,
841 sizeof(at->vec.autn)));
842 vty_out(vty, "RES: %s, ",
Max34604c22019-02-13 14:11:29 +0100843 osmo_hexdump_nospc(at->vec.res, at->vec.res_len));
Harald Welte89837d42016-05-06 23:28:11 +0200844 vty_out(vty, "IK: %s, ",
Max34604c22019-02-13 14:11:29 +0100845 osmo_hexdump_nospc(at->vec.ik, sizeof(at->vec.ik)));
Harald Welte89837d42016-05-06 23:28:11 +0200846 vty_out(vty, "CK: %s, ",
Max34604c22019-02-13 14:11:29 +0100847 osmo_hexdump_nospc(at->vec.ck, sizeof(at->vec.ck)));
Harald Welte89837d42016-05-06 23:28:11 +0200848 }
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100849 }
850
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100851 llist_for_each_entry(pdp, &gsub->sgsn_data->pdp_list, list) {
Max34604c22019-02-13 14:11:29 +0100852 vty_out(vty, " PDP info: Id: %d, Type: 0x%04x, APN: '%s'",
853 pdp->context_id, pdp->pdp_type, pdp->apn_str);
854
855 if (pdp->qos_subscribed_len)
856 vty_out(vty, " QoS: %s", osmo_hexdump(pdp->qos_subscribed, pdp->qos_subscribed_len));
857
858 vty_out(vty, "%s", VTY_NEWLINE);
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100859 }
860
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100861#if 0
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100862 /* print the expiration time of a subscriber */
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100863 if (gsub->expire_lu) {
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100864 strftime(expire_time, sizeof(expire_time),
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100865 "%a, %d %b %Y %T %z", localtime(&gsub->expire_lu));
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100866 expire_time[sizeof(expire_time) - 1] = '\0';
867 vty_out(vty, " Expiration Time: %s%s", expire_time, VTY_NEWLINE);
868 }
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100869#endif
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100870
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100871 if (gsub->flags)
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100872 vty_out(vty, " Flags: %s%s%s%s%s%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100873 gsub->flags & GPRS_SUBSCRIBER_FIRST_CONTACT ?
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100874 "FIRST_CONTACT " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100875 gsub->flags & GPRS_SUBSCRIBER_CANCELLED ?
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100876 "CANCELLED " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100877 gsub->flags & GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING ?
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100878 "UPDATE_LOCATION_PENDING " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100879 gsub->flags & GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING ?
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100880 "AUTH_INFO_PENDING " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100881 gsub->flags & GPRS_SUBSCRIBER_ENABLE_PURGE ?
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100882 "ENABLE_PURGE " : "",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100883 VTY_NEWLINE);
884
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100885 vty_out(vty, " Use count: %u%s", gsub->use_count, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100886}
887
Neels Hofmeyr1a9414b2018-09-24 18:14:29 +0200888#define RESET_SGSN_STATE_STR \
889 "Remove all known subscribers, MM contexts and flush BSSGP queues." \
890 " Useful only when running tests against the SGSN\n"
891
Alexander Couzensc503f0a2018-08-07 17:50:04 +0200892DEFUN_HIDDEN(reset_sgsn_state,
893 reset_sgsn_state_cmd,
894 "reset sgsn state",
Neels Hofmeyr1a9414b2018-09-24 18:14:29 +0200895 RESET_SGSN_STATE_STR RESET_SGSN_STATE_STR RESET_SGSN_STATE_STR)
Alexander Couzensc503f0a2018-08-07 17:50:04 +0200896{
897 struct gprs_subscr *subscr, *tmp_subscr;
898 struct sgsn_mm_ctx *mm, *tmp_mm;
899
900 llist_for_each_entry_safe(mm, tmp_mm, &sgsn_mm_ctxts, list)
901 {
902 gsm0408_gprs_access_cancelled(mm, SGSN_ERROR_CAUSE_NONE);
903 }
904 vty_out(vty, "Cancelled MM Ctx. %s", VTY_NEWLINE);
905
906 llist_for_each_entry_safe(subscr, tmp_subscr, gprs_subscribers, entry) {
907 gprs_subscr_get(subscr);
908 gprs_subscr_cancel(subscr);
909 gprs_subscr_put(subscr);
910 }
911 vty_out(vty, "Removed all gprs subscribers.%s", VTY_NEWLINE);
912
913 bssgp_flush_all_queues();
914 vty_out(vty, "Flushed all BSSGPs queues.%s", VTY_NEWLINE);
915
Alexander Couzens35c34942018-09-17 04:39:14 +0200916 gtp_clear_queues(sgsn->gsn);
Alexander Couzensa66f0f22018-09-18 16:09:18 +0200917 vty_out(vty, "Flushed rx & tx queus towards the GGSN.%s", VTY_NEWLINE);
Alexander Couzens35c34942018-09-17 04:39:14 +0200918
Alexander Couzensc503f0a2018-08-07 17:50:04 +0200919 /* remove all queues to bssgp */
920 return CMD_SUCCESS;
921}
922
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100923DEFUN(show_subscr_cache,
924 show_subscr_cache_cmd,
925 "show subscriber cache",
926 SHOW_STR "Show information about subscribers\n"
927 "Display contents of subscriber cache\n")
928{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100929 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100930
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100931 llist_for_each_entry(subscr, gprs_subscribers, entry) {
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100932 vty_out(vty, " Subscriber:%s", VTY_NEWLINE);
933 subscr_dump_full_vty(vty, subscr, 0);
934 }
935
936 return CMD_SUCCESS;
937}
938
939#define UPDATE_SUBSCR_STR "update-subscriber imsi IMSI "
940#define UPDATE_SUBSCR_HELP "Update subscriber list\n" \
941 "Use the IMSI to select the subscriber\n" \
942 "The IMSI\n"
943
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100944#define UPDATE_SUBSCR_INSERT_HELP "Insert data into the subscriber record\n"
945
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100946DEFUN(update_subscr_insert_auth_triplet, update_subscr_insert_auth_triplet_cmd,
947 UPDATE_SUBSCR_STR "insert auth-triplet <1-5> sres SRES rand RAND kc KC",
948 UPDATE_SUBSCR_HELP
949 UPDATE_SUBSCR_INSERT_HELP
950 "Update authentication triplet\n"
951 "Triplet index\n"
952 "Set SRES value\nSRES value (4 byte) in hex\n"
953 "Set RAND value\nRAND value (16 byte) in hex\n"
954 "Set Kc value\nKc value (8 byte) in hex\n")
955{
956 const char *imsi = argv[0];
957 const int cksn = atoi(argv[1]) - 1;
958 const char *sres_str = argv[2];
959 const char *rand_str = argv[3];
960 const char *kc_str = argv[4];
961 struct gsm_auth_tuple at = {0,};
962
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100963 struct gprs_subscr *subscr;
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100964
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100965 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100966 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100967 vty_out(vty, "%% unable get subscriber record for %s%s",
968 imsi, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100969 return CMD_WARNING;
970 }
971
972 OSMO_ASSERT(subscr->sgsn_data);
973
Harald Welte121e9a42016-04-20 13:13:19 +0200974 if (osmo_hexparse(sres_str, &at.vec.sres[0], sizeof(at.vec.sres)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100975 vty_out(vty, "%% invalid SRES value '%s'%s",
976 sres_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100977 goto failed;
978 }
Harald Welte121e9a42016-04-20 13:13:19 +0200979 if (osmo_hexparse(rand_str, &at.vec.rand[0], sizeof(at.vec.rand)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100980 vty_out(vty, "%% invalid RAND value '%s'%s",
981 rand_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100982 goto failed;
983 }
Harald Welte121e9a42016-04-20 13:13:19 +0200984 if (osmo_hexparse(kc_str, &at.vec.kc[0], sizeof(at.vec.kc)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100985 vty_out(vty, "%% invalid Kc value '%s'%s",
986 kc_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100987 goto failed;
988 }
989 at.key_seq = cksn;
990
991 subscr->sgsn_data->auth_triplets[cksn] = at;
992 subscr->sgsn_data->auth_triplets_updated = 1;
993
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100994 gprs_subscr_put(subscr);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100995
996 return CMD_SUCCESS;
997
998failed:
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100999 gprs_subscr_put(subscr);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01001000 return CMD_SUCCESS;
1001}
1002
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001003DEFUN(update_subscr_cancel, update_subscr_cancel_cmd,
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +01001004 UPDATE_SUBSCR_STR "cancel (update-procedure|subscription-withdraw)",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001005 UPDATE_SUBSCR_HELP
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +01001006 "Cancel (remove) subscriber record\n"
1007 "The MS moved to another SGSN\n"
1008 "The subscription is no longer valid\n")
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001009{
1010 const char *imsi = argv[0];
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +01001011 const char *cancel_type = argv[1];
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001012
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001013 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001014
1015 subscr = gprs_subscr_get_by_imsi(imsi);
1016 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +01001017 vty_out(vty, "%% no subscriber record for %s%s",
1018 imsi, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001019 return CMD_WARNING;
1020 }
1021
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +01001022 if (strcmp(cancel_type, "update-procedure") == 0)
1023 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
1024 else
1025 subscr->sgsn_data->error_cause = GMM_CAUSE_IMPL_DETACHED;
1026
Jacob Erlbeck37139e52015-01-23 13:52:55 +01001027 gprs_subscr_cancel(subscr);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001028 gprs_subscr_put(subscr);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001029
1030 return CMD_SUCCESS;
1031}
1032
Jacob Erlbeckd9193432015-01-19 14:11:46 +01001033DEFUN(update_subscr_create, update_subscr_create_cmd,
1034 UPDATE_SUBSCR_STR "create",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001035 UPDATE_SUBSCR_HELP
Jacob Erlbeckd9193432015-01-19 14:11:46 +01001036 "Create a subscriber entry\n")
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001037{
1038 const char *imsi = argv[0];
1039
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001040 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001041
1042 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +01001043 if (subscr) {
1044 vty_out(vty, "%% subscriber record already exists for %s%s",
1045 imsi, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001046 return CMD_WARNING;
1047 }
1048
Jacob Erlbeckd9193432015-01-19 14:11:46 +01001049 subscr = gprs_subscr_get_or_create(imsi);
Alexander Couzens3326ba72020-12-09 22:02:55 +01001050 if (!subscr) {
1051 vty_out(vty, "Can not create subscriber. Out of memory.%s", imsi);
1052 return CMD_WARNING;
1053 }
Jacob Erlbeckd9193432015-01-19 14:11:46 +01001054 subscr->keep_in_ram = 1;
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001055 gprs_subscr_put(subscr);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001056
1057 return CMD_SUCCESS;
1058}
1059
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001060DEFUN(update_subscr_destroy, update_subscr_destroy_cmd,
1061 UPDATE_SUBSCR_STR "destroy",
1062 UPDATE_SUBSCR_HELP
1063 "Destroy a subscriber entry\n")
1064{
1065 const char *imsi = argv[0];
1066
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001067 struct gprs_subscr *subscr;
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001068
1069 subscr = gprs_subscr_get_by_imsi(imsi);
1070 if (!subscr) {
1071 vty_out(vty, "%% subscriber record does not exist for %s%s",
1072 imsi, VTY_NEWLINE);
1073 return CMD_WARNING;
1074 }
1075
1076 subscr->keep_in_ram = 0;
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +01001077 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001078 gprs_subscr_cancel(subscr);
1079 if (subscr->use_count > 1)
1080 vty_out(vty, "%% subscriber is still in use%s",
1081 VTY_NEWLINE);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001082 gprs_subscr_put(subscr);
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001083
1084 return CMD_SUCCESS;
1085}
1086
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001087#define UL_ERR_STR "system-failure|data-missing|unexpected-data-value|" \
1088 "unknown-subscriber|roaming-not-allowed"
1089
1090#define UL_ERR_HELP \
1091 "Force error code SystemFailure\n" \
1092 "Force error code DataMissing\n" \
1093 "Force error code UnexpectedDataValue\n" \
1094 "Force error code UnknownSubscriber\n" \
1095 "Force error code RoamingNotAllowed\n"
1096
1097DEFUN(update_subscr_update_location_result, update_subscr_update_location_result_cmd,
1098 UPDATE_SUBSCR_STR "update-location-result (ok|" UL_ERR_STR ")",
1099 UPDATE_SUBSCR_HELP
1100 "Complete the update location procedure\n"
1101 "The update location request succeeded\n"
1102 UL_ERR_HELP)
1103{
1104 const char *imsi = argv[0];
1105 const char *ret_code_str = argv[1];
1106
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001107 struct gprs_subscr *subscr;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001108
Jacob Erlbeckd6267d12015-01-19 11:10:04 +01001109 const struct value_string cause_mapping[] = {
1110 { GMM_CAUSE_NET_FAIL, "system-failure" },
1111 { GMM_CAUSE_INV_MAND_INFO, "data-missing" },
1112 { GMM_CAUSE_PROTO_ERR_UNSPEC, "unexpected-data-value" },
1113 { GMM_CAUSE_IMSI_UNKNOWN, "unknown-subscriber" },
1114 { GMM_CAUSE_GPRS_NOTALLOWED, "roaming-not-allowed" },
1115 { 0, NULL }
1116 };
1117
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001118 subscr = gprs_subscr_get_by_imsi(imsi);
1119 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +01001120 vty_out(vty, "%% unable to get subscriber record for %s%s",
1121 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001122 return CMD_WARNING;
1123 }
Jacob Erlbeckd6267d12015-01-19 11:10:04 +01001124
1125 if (strcmp(ret_code_str, "ok") == 0) {
1126 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001127 subscr->authorized = 1;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +01001128 } else {
1129 subscr->sgsn_data->error_cause =
1130 get_string_value(cause_mapping, ret_code_str);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001131 subscr->authorized = 0;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +01001132 }
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001133
1134 gprs_subscr_update(subscr);
1135
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001136 gprs_subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001137
1138 return CMD_SUCCESS;
1139}
1140
1141DEFUN(update_subscr_update_auth_info, update_subscr_update_auth_info_cmd,
1142 UPDATE_SUBSCR_STR "update-auth-info",
1143 UPDATE_SUBSCR_HELP
1144 "Complete the send authentication info procedure\n")
1145{
1146 const char *imsi = argv[0];
1147
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001148 struct gprs_subscr *subscr;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001149
1150 subscr = gprs_subscr_get_by_imsi(imsi);
1151 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +01001152 vty_out(vty, "%% unable to get subscriber record for %s%s",
1153 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001154 return CMD_WARNING;
1155 }
1156
1157 gprs_subscr_update_auth_info(subscr);
1158
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001159 gprs_subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001160
1161 return CMD_SUCCESS;
1162}
1163
Stefan Sperling88220092018-12-11 14:42:00 +01001164DEFUN(cfg_gsup_ipa_name,
1165 cfg_gsup_ipa_name_cmd,
1166 "gsup ipa-name NAME",
1167 "GSUP Parameters\n"
1168 "Set the IPA name of this SGSN\n"
1169 "A unique name for this SGSN. For example: PLMN + redundancy server number: SGSN-901-70-0. "
1170 "This name is used for GSUP routing and must be set if more than one SGSN is connected to the network. "
1171 "The default is 'SGSN-00-00-00-00-00-00'.\n")
1172{
1173 if (vty->type != VTY_FILE) {
1174 vty_out(vty, "The IPA name cannot be changed at run-time; "
1175 "It can only be set in the configuraton file.%s", VTY_NEWLINE);
1176 return CMD_WARNING;
1177 }
1178
1179 g_cfg->sgsn_ipa_name = talloc_strdup(tall_vty_ctx, argv[0]);
1180 return CMD_SUCCESS;
1181}
1182
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001183DEFUN(cfg_gsup_remote_ip, cfg_gsup_remote_ip_cmd,
1184 "gsup remote-ip A.B.C.D",
1185 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001186 "Set the IP address of the remote GSUP server (e.g. OsmoHLR)."
1187 " This setting only applies if 'auth-policy remote' is used.\n"
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001188 "IPv4 Address\n")
1189{
1190 inet_aton(argv[0], &g_cfg->gsup_server_addr.sin_addr);
1191
1192 return CMD_SUCCESS;
1193}
1194
1195DEFUN(cfg_gsup_remote_port, cfg_gsup_remote_port_cmd,
1196 "gsup remote-port <0-65535>",
1197 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001198 "Set the TCP port of the remote GSUP server, see also 'gsup remote-ip'\n"
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001199 "Remote TCP port\n")
1200{
1201 g_cfg->gsup_server_port = atoi(argv[0]);
1202
1203 return CMD_SUCCESS;
1204}
1205
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001206DEFUN(cfg_gsup_oap_id, cfg_gsup_oap_id_cmd,
1207 "gsup oap-id <0-65535>",
1208 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001209 "Set the OAP client ID for authentication on the GSUP protocol."
1210 " This setting only applies if 'auth-policy remote' is used.\n"
1211 "OAP client ID (0 == disabled)\n")
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001212{
1213 /* VTY ensures range */
1214 g_cfg->oap.client_id = (uint16_t)atoi(argv[0]);
1215 return CMD_SUCCESS;
1216}
1217
1218DEFUN(cfg_gsup_oap_k, cfg_gsup_oap_k_cmd,
1219 "gsup oap-k K",
1220 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001221 "Set the OAP shared secret key K for authentication on the GSUP protocol."
1222 " This setting only applies if auth-policy remote is used.\n"
1223 "K value (16 byte) hex\n")
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001224{
1225 const char *k = argv[0];
1226
1227 g_cfg->oap.secret_k_present = 0;
1228
1229 if ((!k) || (strlen(k) == 0))
1230 goto disable;
1231
1232 int k_len = osmo_hexparse(k,
1233 g_cfg->oap.secret_k,
1234 sizeof(g_cfg->oap.secret_k));
1235 if (k_len != 16) {
1236 vty_out(vty, "%% need exactly 16 octets for oap-k, got %d.%s",
1237 k_len, VTY_NEWLINE);
1238 goto disable;
1239 }
1240
1241 g_cfg->oap.secret_k_present = 1;
1242 return CMD_SUCCESS;
1243
1244disable:
1245 if (g_cfg->oap.client_id > 0) {
1246 vty_out(vty, "%% OAP client ID set, but invalid oap-k value disables OAP.%s",
1247 VTY_NEWLINE);
1248 return CMD_WARNING;
1249 }
1250 return CMD_SUCCESS;
1251}
1252
1253DEFUN(cfg_gsup_oap_opc, cfg_gsup_oap_opc_cmd,
1254 "gsup oap-opc OPC",
1255 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001256 "Set the OAP shared secret OPC for authentication on the GSUP protocol."
1257 " This setting only applies if auth-policy remote is used.\n"
1258 "OPC value (16 byte) hex\n")
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001259{
1260 const char *opc = argv[0];
1261
1262 g_cfg->oap.secret_opc_present = 0;
1263
1264 if ((!opc) || (strlen(opc) == 0))
1265 goto disable;
1266
1267 int opc_len = osmo_hexparse(opc,
1268 g_cfg->oap.secret_opc,
1269 sizeof(g_cfg->oap.secret_opc));
1270 if (opc_len != 16) {
1271 vty_out(vty, "%% need exactly 16 octets for oap-opc, got %d.%s",
1272 opc_len, VTY_NEWLINE);
1273 goto disable;
1274 }
1275
1276 g_cfg->oap.secret_opc_present = 1;
1277 return CMD_SUCCESS;
1278
1279disable:
1280 if (g_cfg->oap.client_id > 0) {
1281 vty_out(vty, "%% OAP client ID set, but invalid oap-opc value disables OAP.%s",
1282 VTY_NEWLINE);
1283 return CMD_WARNING;
1284 }
1285 return CMD_SUCCESS;
1286}
1287
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001288DEFUN(cfg_apn_name, cfg_apn_name_cmd,
1289 "access-point-name NAME",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001290 "Globally allow the given APN name for all subscribers.\n"
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001291 "Add this NAME to the list\n")
1292{
1293 return add_apn_ggsn_mapping(vty, argv[0], "", 0);
1294}
1295
1296DEFUN(cfg_no_apn_name, cfg_no_apn_name_cmd,
1297 "no access-point-name NAME",
1298 NO_STR "Configure a global list of allowed APNs\n"
1299 "Remove entry with NAME\n")
1300{
1301 struct apn_ctx *apn_ctx = sgsn_apn_ctx_by_name(argv[0], "");
1302 if (!apn_ctx)
1303 return CMD_SUCCESS;
1304
1305 sgsn_apn_ctx_free(apn_ctx);
1306 return CMD_SUCCESS;
1307}
1308
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001309DEFUN(cfg_cdr_filename, cfg_cdr_filename_cmd,
1310 "cdr filename NAME",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001311 "CDR\n"
1312 "Set the file name for the call-data-record file, logging the data usage of each subscriber.\n"
1313 "filename\n")
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001314{
1315 talloc_free(g_cfg->cdr.filename);
1316 g_cfg->cdr.filename = talloc_strdup(tall_vty_ctx, argv[0]);
1317 return CMD_SUCCESS;
1318}
1319
1320DEFUN(cfg_no_cdr_filename, cfg_no_cdr_filename_cmd,
1321 "no cdr filename",
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +01001322 NO_STR "CDR\nDisable saving CDR to file\n")
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001323{
1324 talloc_free(g_cfg->cdr.filename);
1325 g_cfg->cdr.filename = NULL;
1326 return CMD_SUCCESS;
1327}
1328
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +01001329DEFUN(cfg_cdr_trap, cfg_cdr_trap_cmd,
1330 "cdr trap",
1331 "CDR\nEnable sending CDR via TRAP CTRL messages\n")
1332{
1333 g_cfg->cdr.trap = true;
1334 return CMD_SUCCESS;
1335}
1336
1337DEFUN(cfg_no_cdr_trap, cfg_no_cdr_trap_cmd,
1338 "no cdr trap",
1339 NO_STR "CDR\nDisable sending CDR via TRAP CTRL messages\n")
1340{
1341 g_cfg->cdr.trap = false;
1342 return CMD_SUCCESS;
1343}
1344
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001345DEFUN(cfg_cdr_interval, cfg_cdr_interval_cmd,
1346 "cdr interval <1-2147483647>",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001347 "CDR\n"
1348 "Set the interval for the call-data-record file\n"
1349 "interval in seconds\n")
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001350{
1351 g_cfg->cdr.interval = atoi(argv[0]);
1352 return CMD_SUCCESS;
1353}
1354
Philippf1f34362016-08-26 17:00:21 +02001355#define COMPRESSION_STR "Configure compression\n"
1356DEFUN(cfg_no_comp_rfc1144, cfg_no_comp_rfc1144_cmd,
1357 "no compression rfc1144",
1358 NO_STR COMPRESSION_STR "disable rfc1144 TCP/IP header compression\n")
1359{
1360 g_cfg->pcomp_rfc1144.active = 0;
1361 g_cfg->pcomp_rfc1144.passive = 0;
1362 return CMD_SUCCESS;
1363}
1364
1365DEFUN(cfg_comp_rfc1144, cfg_comp_rfc1144_cmd,
1366 "compression rfc1144 active slots <1-256>",
1367 COMPRESSION_STR
Ruben Undheim55fcf112018-09-25 22:59:34 +02001368 "RFC1144 Header compression scheme\n"
Philippf1f34362016-08-26 17:00:21 +02001369 "Compression is actively proposed\n"
1370 "Number of compression state slots\n"
1371 "Number of compression state slots\n")
1372{
1373 g_cfg->pcomp_rfc1144.active = 1;
1374 g_cfg->pcomp_rfc1144.passive = 1;
1375 g_cfg->pcomp_rfc1144.s01 = atoi(argv[0]) - 1;
1376 return CMD_SUCCESS;
1377}
1378
1379DEFUN(cfg_comp_rfc1144p, cfg_comp_rfc1144p_cmd,
1380 "compression rfc1144 passive",
1381 COMPRESSION_STR
Ruben Undheim55fcf112018-09-25 22:59:34 +02001382 "RFC1144 Header compression scheme\n"
Philippf1f34362016-08-26 17:00:21 +02001383 "Compression is available on request\n")
1384{
1385 g_cfg->pcomp_rfc1144.active = 0;
1386 g_cfg->pcomp_rfc1144.passive = 1;
1387 return CMD_SUCCESS;
1388}
1389
Philipp73f83d52016-09-02 13:38:01 +02001390DEFUN(cfg_no_comp_v42bis, cfg_no_comp_v42bis_cmd,
1391 "no compression v42bis",
1392 NO_STR COMPRESSION_STR "disable V.42bis data compression\n")
1393{
1394 g_cfg->dcomp_v42bis.active = 0;
1395 g_cfg->dcomp_v42bis.passive = 0;
1396 return CMD_SUCCESS;
1397}
1398
1399DEFUN(cfg_comp_v42bis, cfg_comp_v42bis_cmd,
1400 "compression v42bis active direction (ms|sgsn|both) codewords <512-65535> strlen <6-250>",
1401 COMPRESSION_STR
Ruben Undheim55fcf112018-09-25 22:59:34 +02001402 "V.42bis data compression scheme\n"
Philipp73f83d52016-09-02 13:38:01 +02001403 "Compression is actively proposed\n"
1404 "Direction in which the compression shall be active (p0)\n"
1405 "Compress ms->sgsn direction only\n"
1406 "Compress sgsn->ms direction only\n"
1407 "Both directions\n"
1408 "Number of codewords (p1)\n"
1409 "Number of codewords\n"
1410 "Maximum string length (p2)\n" "Maximum string length\n")
1411{
1412 g_cfg->dcomp_v42bis.active = 1;
1413 g_cfg->dcomp_v42bis.passive = 1;
1414
1415 switch (argv[0][0]) {
1416 case 'm':
1417 g_cfg->dcomp_v42bis.p0 = 1;
1418 break;
1419 case 's':
1420 g_cfg->dcomp_v42bis.p0 = 2;
1421 break;
1422 case 'b':
1423 g_cfg->dcomp_v42bis.p0 = 3;
1424 break;
1425 }
1426
1427 g_cfg->dcomp_v42bis.p1 = atoi(argv[1]);
1428 g_cfg->dcomp_v42bis.p2 = atoi(argv[2]);
1429 return CMD_SUCCESS;
1430}
1431
1432DEFUN(cfg_comp_v42bisp, cfg_comp_v42bisp_cmd,
1433 "compression v42bis passive",
1434 COMPRESSION_STR
Ruben Undheim55fcf112018-09-25 22:59:34 +02001435 "V.42bis data compression scheme\n"
Philipp73f83d52016-09-02 13:38:01 +02001436 "Compression is available on request\n")
1437{
1438 g_cfg->dcomp_v42bis.active = 0;
1439 g_cfg->dcomp_v42bis.passive = 1;
1440 return CMD_SUCCESS;
1441}
1442
Pau Espin Pedrol2c908992019-08-19 19:06:06 +02001443#if BUILD_IU
1444DEFUN(cfg_sgsn_cs7_instance_iu,
1445 cfg_sgsn_cs7_instance_iu_cmd,
1446 "cs7-instance-iu <0-15>",
1447 "Set SS7 to be used by the Iu-Interface.\n" "SS7 instance reference number (default: 0)\n")
1448{
1449 g_cfg->iu.cs7_instance = atoi(argv[0]);
1450 return CMD_SUCCESS;
1451}
1452#endif
1453
Pau Espin Pedrole5c89982021-05-03 18:16:42 +02001454DEFUN(cfg_sgsn_mme, cfg_sgsn_mme_cmd,
1455 "mme NAME",
1456 "Configure an MME peer\n"
1457 "Name identifying the MME peer\n")
1458{
1459 struct sgsn_mme_ctx *mme;
1460
1461 mme = sgsn_mme_ctx_find_alloc(sgsn, argv[0]);
1462 if (!mme)
1463 return CMD_WARNING;
1464
1465 vty->node = MME_NODE;
1466 vty->index = mme;
1467
1468 return CMD_SUCCESS;
1469}
1470
1471DEFUN(cfg_sgsn_no_mme, cfg_sgsn_no_mme_cmd,
1472 "no mme NAME",
1473 NO_STR "Delete an MME peer configuration\n"
1474 "Name identifying the MME peer\n")
1475{
1476 struct sgsn_mme_ctx *mme;
1477
1478 mme = sgsn_mme_ctx_by_name(sgsn, argv[0]);
1479 if (!mme) {
1480 vty_out(vty, "%% MME %s doesn't exist.%s",
1481 argv[0], VTY_NEWLINE);
1482 return CMD_WARNING;
1483 }
1484
1485 sgsn_mme_ctx_free(mme);
1486
1487 return CMD_SUCCESS;
1488}
1489
1490#define GTP_STR "Configure GTP connection\n"
1491
1492DEFUN(cfg_mme_remote_ip, cfg_mme_remote_ip_cmd,
1493 "gtp remote-ip A.B.C.D",
1494 GTP_STR "Set Remote GTP IP address\n" IP_STR)
1495{
1496 struct sgsn_mme_ctx *mme = (struct sgsn_mme_ctx *) vty->index;
1497
1498 inet_aton(argv[0], &mme->remote_addr);
1499
1500 return CMD_SUCCESS;
1501}
1502
1503#define RAN_INFO_STR "Configure RAN Information Relay routing\n"
1504#define TAI_DOC "MCC\n" "MNC\n" "TAC\n"
1505
1506DEFUN(cfg_mme_ran_info_relay_tai, cfg_mme_ran_info_relay_tai_cmd,
1507 "gtp ran-info-relay <0-999> <0-999> <0-65535>",
1508 GTP_STR RAN_INFO_STR TAI_DOC)
1509{
1510 struct sgsn_mme_ctx *mme = (struct sgsn_mme_ctx *) vty->index;
1511 struct sgsn_mme_ctx *mme_tmp;
1512 struct osmo_eutran_tai tai;
1513
1514 const char *mcc = argv[0];
1515 const char *mnc = argv[1];
1516 const char *tac = argv[2];
1517
1518 if (osmo_mcc_from_str(mcc, &tai.mcc)) {
1519 vty_out(vty, "%% Error decoding MCC: %s%s", mcc, VTY_NEWLINE);
1520 return CMD_WARNING;
1521 }
1522 if (osmo_mnc_from_str(mnc, &tai.mnc, &tai.mnc_3_digits)) {
1523 vty_out(vty, "%% Error decoding MNC: %s%s", mnc, VTY_NEWLINE);
1524 return CMD_WARNING;
1525 }
1526 tai.tac = atoi(tac);
1527
1528 if ((mme_tmp = sgsn_mme_ctx_by_route(sgsn, &tai))) {
1529 if (mme_tmp != mme) {
1530 vty_out(vty, "%% Another MME %s already contains this route%s",
1531 mme_tmp->name, VTY_NEWLINE);
1532 return CMD_WARNING;
1533 }
1534 /* else: NO-OP, return */
1535 return CMD_SUCCESS;
1536 }
1537
1538 sgsn_mme_ctx_route_add(mme, &tai);
1539 return CMD_SUCCESS;
1540}
1541
1542DEFUN(cfg_mme_no_ran_info_relay_tai, cfg_mme_no_ran_info_relay_tai_cmd,
1543 "no gtp ran-info-relay <0-999> <0-999> <0-65535>",
1544 NO_STR GTP_STR RAN_INFO_STR TAI_DOC)
1545{
1546 struct sgsn_mme_ctx *mme = (struct sgsn_mme_ctx *) vty->index;
1547 struct sgsn_mme_ctx *mme_tmp;
1548 struct osmo_eutran_tai tai;
1549
1550 const char *mcc = argv[0];
1551 const char *mnc = argv[1];
1552 const char *tac = argv[2];
1553
1554 if (osmo_mcc_from_str(mcc, &tai.mcc)) {
1555 vty_out(vty, "%% Error decoding MCC: %s%s", mcc, VTY_NEWLINE);
1556 return CMD_WARNING;
1557 }
1558 if (osmo_mnc_from_str(mnc, &tai.mnc, &tai.mnc_3_digits)) {
1559 vty_out(vty, "%% Error decoding MNC: %s%s", mnc, VTY_NEWLINE);
1560 return CMD_WARNING;
1561 }
1562 tai.tac = atoi(tac);
1563
1564 if ((mme_tmp = sgsn_mme_ctx_by_route(sgsn, &tai))) {
1565 if (mme_tmp != mme) {
1566 vty_out(vty, "%% Another MME %s contains this route%s",
1567 mme_tmp->name, VTY_NEWLINE);
1568 return CMD_WARNING;
1569 }
1570 sgsn_mme_ctx_route_del(mme, &tai);
1571 return CMD_SUCCESS;
1572 } else {
1573 vty_out(vty, "%% This route doesn't exist in current MME %s%s",
1574 mme->name, VTY_NEWLINE);
1575 return CMD_WARNING;
1576 }
1577}
1578
1579DEFUN(cfg_mme_ran_info_relay_default, cfg_mme_ran_info_relay_default_cmd,
1580 "gtp ran-info-relay default",
1581 GTP_STR RAN_INFO_STR "Set as default route")
1582{
1583 struct sgsn_mme_ctx *mme = (struct sgsn_mme_ctx *) vty->index;
1584 struct sgsn_mme_ctx *default_mme;
1585
1586 if (mme->default_route)
1587 return CMD_SUCCESS; /* NO-OP */
1588
1589 if ((default_mme = sgsn_mme_ctx_by_default_route(sgsn))) {
1590 vty_out(vty, "%% Another MME %s is already set as default route, "
1591 "remove it before setting it here.%s",
1592 default_mme->name, VTY_NEWLINE);
1593 return CMD_WARNING;
1594 }
1595
1596 mme->default_route = true;
1597 return CMD_SUCCESS;
1598}
1599
1600DEFUN(cfg_mme_no_ran_info_relay_default, cfg_mme_no_ran_info_relay_default_cmd,
1601 "no gtp ran-info-relay default",
1602 NO_STR GTP_STR RAN_INFO_STR "Set as default route")
1603{
1604 struct sgsn_mme_ctx *mme = (struct sgsn_mme_ctx *) vty->index;
1605 mme->default_route = false;
1606 return CMD_SUCCESS;
1607}
1608
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001609int sgsn_vty_init(struct sgsn_config *cfg)
Harald Welte288be162010-05-01 16:48:27 +02001610{
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001611 g_cfg = cfg;
1612
Pau Espin Pedrola299d652019-08-14 19:11:10 +02001613 g_cfg->T_defs = sgsn_T_defs;
1614 osmo_tdefs_reset(g_cfg->T_defs);
1615
Harald Welted193cb32010-05-17 22:58:03 +02001616 install_element_ve(&show_sgsn_cmd);
1617 //install_element_ve(&show_mmctx_tlli_cmd);
1618 install_element_ve(&show_mmctx_imsi_cmd);
1619 install_element_ve(&show_mmctx_all_cmd);
1620 install_element_ve(&show_pdpctx_all_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001621 install_element_ve(&show_subscr_cache_cmd);
Pau Espin Pedrola299d652019-08-14 19:11:10 +02001622 install_element_ve(&show_timer_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001623
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01001624 install_element(ENABLE_NODE, &update_subscr_insert_auth_triplet_cmd);
Jacob Erlbeckd9193432015-01-19 14:11:46 +01001625 install_element(ENABLE_NODE, &update_subscr_create_cmd);
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001626 install_element(ENABLE_NODE, &update_subscr_destroy_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001627 install_element(ENABLE_NODE, &update_subscr_cancel_cmd);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001628 install_element(ENABLE_NODE, &update_subscr_update_location_result_cmd);
1629 install_element(ENABLE_NODE, &update_subscr_update_auth_info_cmd);
Alexander Couzensc503f0a2018-08-07 17:50:04 +02001630 install_element(ENABLE_NODE, &reset_sgsn_state_cmd);
Harald Welte288be162010-05-01 16:48:27 +02001631
1632 install_element(CONFIG_NODE, &cfg_sgsn_cmd);
1633 install_node(&sgsn_node, config_write_sgsn);
Keithc70e8382020-10-19 22:24:48 +02001634 install_element(SGSN_NODE, &cfg_sgsn_state_dir_cmd);
Harald Weltee300d002010-06-02 12:41:34 +02001635 install_element(SGSN_NODE, &cfg_sgsn_bind_addr_cmd);
Harald Welted193cb32010-05-17 22:58:03 +02001636 install_element(SGSN_NODE, &cfg_ggsn_remote_ip_cmd);
1637 //install_element(SGSN_NODE, &cfg_ggsn_remote_port_cmd);
1638 install_element(SGSN_NODE, &cfg_ggsn_gtp_version_cmd);
Pau Espin Pedrolfa120102018-07-09 20:37:47 +02001639 install_element(SGSN_NODE, &cfg_ggsn_echo_interval_cmd);
Pau Espin Pedrola83850c2018-07-10 12:43:59 +02001640 install_element(SGSN_NODE, &cfg_ggsn_no_echo_interval_cmd);
Harald Welte7f6da482013-03-19 11:00:13 +01001641 install_element(SGSN_NODE, &cfg_imsi_acl_cmd);
Harald Welte3dfb5492013-03-19 11:48:54 +01001642 install_element(SGSN_NODE, &cfg_auth_policy_cmd);
Vadim Yanitskiy794f4462019-05-27 05:39:06 +07001643 install_element(SGSN_NODE, &cfg_authentication_cmd);
Max93408ae2016-06-28 14:10:16 +02001644 install_element(SGSN_NODE, &cfg_encrypt_cmd);
Stefan Sperling88220092018-12-11 14:42:00 +01001645 install_element(SGSN_NODE, &cfg_gsup_ipa_name_cmd);
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001646 install_element(SGSN_NODE, &cfg_gsup_remote_ip_cmd);
1647 install_element(SGSN_NODE, &cfg_gsup_remote_port_cmd);
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001648 install_element(SGSN_NODE, &cfg_gsup_oap_id_cmd);
1649 install_element(SGSN_NODE, &cfg_gsup_oap_k_cmd);
1650 install_element(SGSN_NODE, &cfg_gsup_oap_opc_cmd);
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +01001651 install_element(SGSN_NODE, &cfg_apn_ggsn_cmd);
1652 install_element(SGSN_NODE, &cfg_apn_imsi_ggsn_cmd);
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001653 install_element(SGSN_NODE, &cfg_apn_name_cmd);
1654 install_element(SGSN_NODE, &cfg_no_apn_name_cmd);
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001655 install_element(SGSN_NODE, &cfg_cdr_filename_cmd);
1656 install_element(SGSN_NODE, &cfg_no_cdr_filename_cmd);
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +01001657 install_element(SGSN_NODE, &cfg_cdr_trap_cmd);
1658 install_element(SGSN_NODE, &cfg_no_cdr_trap_cmd);
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001659 install_element(SGSN_NODE, &cfg_cdr_interval_cmd);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001660 install_element(SGSN_NODE, &cfg_ggsn_dynamic_lookup_cmd);
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +08001661 install_element(SGSN_NODE, &cfg_grx_ggsn_cmd);
Harald Welte288be162010-05-01 16:48:27 +02001662
Pau Espin Pedrola299d652019-08-14 19:11:10 +02001663 install_element(SGSN_NODE, &cfg_sgsn_timer_cmd);
Harald Welte94508822015-08-15 19:08:21 +02001664
Philippf1f34362016-08-26 17:00:21 +02001665 install_element(SGSN_NODE, &cfg_no_comp_rfc1144_cmd);
1666 install_element(SGSN_NODE, &cfg_comp_rfc1144_cmd);
1667 install_element(SGSN_NODE, &cfg_comp_rfc1144p_cmd);
Philipp73f83d52016-09-02 13:38:01 +02001668 install_element(SGSN_NODE, &cfg_no_comp_v42bis_cmd);
1669 install_element(SGSN_NODE, &cfg_comp_v42bis_cmd);
1670 install_element(SGSN_NODE, &cfg_comp_v42bisp_cmd);
Neels Hofmeyr2188a772016-05-20 21:59:55 +02001671
Pau Espin Pedrole5c89982021-05-03 18:16:42 +02001672 install_element(SGSN_NODE, &cfg_sgsn_mme_cmd);
1673 install_element(SGSN_NODE, &cfg_sgsn_no_mme_cmd);
1674 install_node(&mme_node, NULL);
1675 install_element(MME_NODE, &cfg_mme_remote_ip_cmd);
1676 install_element(MME_NODE, &cfg_mme_ran_info_relay_default_cmd);
1677 install_element(MME_NODE, &cfg_mme_no_ran_info_relay_default_cmd);
1678 install_element(MME_NODE, &cfg_mme_ran_info_relay_tai_cmd);
1679 install_element(MME_NODE, &cfg_mme_no_ran_info_relay_tai_cmd);
1680
Neels Hofmeyr2188a772016-05-20 21:59:55 +02001681#ifdef BUILD_IU
Pau Espin Pedrol2c908992019-08-19 19:06:06 +02001682 install_element(SGSN_NODE, &cfg_sgsn_cs7_instance_iu_cmd);
Neels Hofmeyra7a39472017-07-05 15:19:52 +02001683 ranap_iu_vty_init(SGSN_NODE, &g_cfg->iu.rab_assign_addr_enc);
Neels Hofmeyr2188a772016-05-20 21:59:55 +02001684#endif
Harald Welte288be162010-05-01 16:48:27 +02001685 return 0;
1686}
1687
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001688int sgsn_parse_config(const char *config_file)
Harald Welte288be162010-05-01 16:48:27 +02001689{
1690 int rc;
1691
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001692 /* make sure sgsn_vty_init() was called before this */
1693 OSMO_ASSERT(g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +01001694
Harald Weltedcccb182010-05-16 20:52:23 +02001695 rc = vty_read_config_file(config_file, NULL);
Harald Welte288be162010-05-01 16:48:27 +02001696 if (rc < 0) {
1697 fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
1698 return rc;
1699 }
1700
Neels Hofmeyr27355c92017-02-24 06:28:31 +01001701 if (g_cfg->auth_policy == SGSN_AUTH_POLICY_REMOTE
1702 && !(g_cfg->gsup_server_addr.sin_addr.s_addr
1703 && g_cfg->gsup_server_port)) {
1704 fprintf(stderr, "Configuration error:"
1705 " 'auth-policy remote' requires both"
1706 " 'gsup remote-ip' and 'gsup remote-port'\n");
1707 return -EINVAL;
1708 }
1709
Harald Welte288be162010-05-01 16:48:27 +02001710 return 0;
1711}