blob: a394c419c420ff5706ebd99bec1fef6631946405 [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>
Oliver Smithab39b622021-07-05 15:41:05 +020038#include <osmocom/sgsn/gprs_gb.h>
Alexander Couzensc503f0a2018-08-07 17:50:04 +020039#include <osmocom/sgsn/gprs_gmm.h>
Neels Hofmeyr396f2e62017-09-04 15:13:25 +020040#include <osmocom/sgsn/gprs_sgsn.h>
Pau Espin Pedrole5c89982021-05-03 18:16:42 +020041#include <osmocom/sgsn/gtp_mme.h>
Neels Hofmeyr396f2e62017-09-04 15:13:25 +020042#include <osmocom/sgsn/vty.h>
Harald Weltef4b2c4c2018-09-16 07:53:41 +020043#include <osmocom/gsupclient/gsup_client.h>
Harald Welte288be162010-05-01 16:48:27 +020044
Pau Espin Pedrola299d652019-08-14 19:11:10 +020045#include <osmocom/vty/tdef_vty.h>
Harald Welte4b037e42010-05-19 19:45:32 +020046#include <osmocom/vty/command.h>
47#include <osmocom/vty/vty.h>
Pablo Neira Ayuso6110a3f2011-03-28 19:35:00 +020048#include <osmocom/vty/misc.h>
Max93408ae2016-06-28 14:10:16 +020049#include <osmocom/crypt/gprs_cipher.h>
Neels Hofmeyr3c7656a2022-03-07 15:38:59 +010050#include <osmocom/crypt/utran_cipher.h>
Jacob Erlbeck80547992014-12-19 19:19:46 +010051#include <osmocom/abis/ipa.h>
52
Alexander Couzensc503f0a2018-08-07 17:50:04 +020053#include <osmocom/gprs/gprs_bssgp.h>
54
Harald Welted193cb32010-05-17 22:58:03 +020055#include <pdp.h>
Maxbaabc682017-10-20 13:39:57 +020056#include <gtp.h>
Harald Welted193cb32010-05-17 22:58:03 +020057
Neels Hofmeyr2188a772016-05-20 21:59:55 +020058#include "../../bscconfig.h"
59
60#ifdef BUILD_IU
Neels Hofmeyra7a39472017-07-05 15:19:52 +020061#include <osmocom/ranap/iu_client.h>
Neels Hofmeyr2188a772016-05-20 21:59:55 +020062#endif
63
Pau Espin Pedrolb1d1c242018-10-30 17:27:59 +010064extern void *tall_sgsn_ctx;
Neels Hofmeyree6cfdc2017-07-13 02:03:50 +020065
Harald Welte288be162010-05-01 16:48:27 +020066static struct sgsn_config *g_cfg = NULL;
67
Jacob Erlbeck106f5472014-11-04 10:08:37 +010068const struct value_string sgsn_auth_pol_strs[] = {
69 { SGSN_AUTH_POLICY_OPEN, "accept-all" },
70 { SGSN_AUTH_POLICY_CLOSED, "closed" },
71 { SGSN_AUTH_POLICY_ACL_ONLY, "acl-only" },
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +010072 { SGSN_AUTH_POLICY_REMOTE, "remote" },
Jacob Erlbeck106f5472014-11-04 10:08:37 +010073 { 0, NULL }
74};
75
Harald Welte94508822015-08-15 19:08:21 +020076/* Section 11.2.2 / Table 11.3a GPRS Mobility management timers – MS side */
77#define GSM0408_T3312_SECS (10*60) /* periodic RAU interval, default 54min */
78
79/* Section 11.2.2 / Table 11.4 MM timers netwokr side */
80#define GSM0408_T3322_SECS 6 /* DETACH_REQ -> DETACH_ACC */
81#define GSM0408_T3350_SECS 6 /* waiting for ATT/RAU/TMSI COMPL */
82#define GSM0408_T3360_SECS 6 /* waiting for AUTH/CIPH RESP */
83#define GSM0408_T3370_SECS 6 /* waiting for ID RESP */
84
Alexander Couzens5ba6fb32017-01-31 18:04:27 +010085/* Section 11.2.2 / Table 11.4a MM timers network side */
Harald Welte94508822015-08-15 19:08:21 +020086#define GSM0408_T3313_SECS 30 /* waiting for paging response */
87#define GSM0408_T3314_SECS 44 /* force to STBY on expiry, Ready timer */
88#define GSM0408_T3316_SECS 44
89
90/* Section 11.3 / Table 11.2d Timers of Session Management - network side */
91#define GSM0408_T3385_SECS 8 /* wait for ACT PDP CTX REQ */
92#define GSM0408_T3386_SECS 8 /* wait for MODIFY PDP CTX ACK */
93#define GSM0408_T3395_SECS 8 /* wait for DEACT PDP CTX ACK */
94#define GSM0408_T3397_SECS 8 /* wait for DEACT AA PDP CTX ACK */
95
Alexander Couzensafadd102019-10-08 14:30:59 +020096/* Non spec timer */
97#define NONSPEC_X1001_SECS 5 /* wait for a RANAP Release Complete */
98
Pau Espin Pedrola299d652019-08-14 19:11:10 +020099
100static struct osmo_tdef sgsn_T_defs[] = {
101 { .T=3312, .default_val=GSM0408_T3312_SECS, .desc="Periodic RA Update timer (s)" },
102 { .T=3313, .default_val=GSM0408_T3313_SECS, .desc="Waiting for paging response timer (s)" },
Alexander Couzens39cbecd2017-02-03 22:16:05 +0100103 { .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 +0200104 { .T=3316, .default_val=GSM0408_T3316_SECS, .desc="AA-Ready timer (s)" },
105 { .T=3322, .default_val=GSM0408_T3322_SECS, .desc="Detach request -> accept timer (s)" },
106 { .T=3350, .default_val=GSM0408_T3350_SECS, .desc="Waiting for ATT/RAU/TMSI_COMPL timer (s)" },
107 { .T=3360, .default_val=GSM0408_T3360_SECS, .desc="Waiting for AUTH/CIPH response timer (s)" },
108 { .T=3370, .default_val=GSM0408_T3370_SECS, .desc="Waiting for IDENTITY response timer (s)" },
109 { .T=3385, .default_val=GSM0408_T3385_SECS, .desc="Wait for ACT PDP CTX REQ timer (s)" },
110 { .T=3386, .default_val=GSM0408_T3386_SECS, .desc="Wait for MODIFY PDP CTX ACK timer (s)" },
111 { .T=3395, .default_val=GSM0408_T3395_SECS, .desc="Wait for DEACT PDP CTX ACK timer (s)" },
112 { .T=3397, .default_val=GSM0408_T3397_SECS, .desc="Wait for DEACT AA PDP CTX ACK timer (s)" },
Alexander Couzens3bad31b2019-09-11 02:17:31 +0200113 /* non spec timers */
Alexander Couzensafadd102019-10-08 14:30:59 +0200114 { .T=-1001, .default_val=NONSPEC_X1001_SECS, .desc="RANAP Release timeout. Wait for RANAP Release Complete."
115 "On expiry release Iu connection (s)" },
Pau Espin Pedrola299d652019-08-14 19:11:10 +0200116 {}
117};
118
119DEFUN(show_timer, show_timer_cmd,
120 "show timer " OSMO_TDEF_VTY_ARG_T_OPTIONAL,
121 SHOW_STR "Show timers\n"
122 OSMO_TDEF_VTY_DOC_T)
123{
124 const char *T_arg = argc > 0 ? argv[0] : NULL;
125 return osmo_tdef_vty_show_cmd(vty, g_cfg->T_defs, T_arg, NULL);
Harald Welte94508822015-08-15 19:08:21 +0200126}
127
Pau Espin Pedrola299d652019-08-14 19:11:10 +0200128DEFUN(cfg_sgsn_timer, cfg_sgsn_timer_cmd,
129 "timer " OSMO_TDEF_VTY_ARG_SET_OPTIONAL,
130 "Configure or show timers\n"
131 OSMO_TDEF_VTY_DOC_SET)
132{
133 /* If any arguments are missing, redirect to 'show' */
134 if (argc < 2)
135 return show_timer(self, vty, argc, argv);
136 return osmo_tdef_vty_set_cmd(vty, g_cfg->T_defs, argv);
137}
Harald Welte94508822015-08-15 19:08:21 +0200138
Keith6cee1a12021-09-29 21:00:04 +0200139char *gprs_pdpaddr2str(uint8_t *pdpa, uint8_t len, bool return_ipv6)
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200140{
141 static char str[INET6_ADDRSTRLEN + 10];
142
143 if (!pdpa || len < 2)
144 return "none";
145
146 switch (pdpa[0] & 0x0f) {
147 case PDP_TYPE_ORG_IETF:
148 switch (pdpa[1]) {
149 case PDP_TYPE_N_IETF_IPv4:
150 if (len < 2 + 4)
151 break;
Keith6cee1a12021-09-29 21:00:04 +0200152 osmo_strlcpy(str, "IPv4 ", sizeof(str));
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200153 inet_ntop(AF_INET, pdpa+2, str+5, sizeof(str)-5);
154 return str;
155 case PDP_TYPE_N_IETF_IPv6:
156 if (len < 2 + 8)
157 break;
Keith6cee1a12021-09-29 21:00:04 +0200158 osmo_strlcpy(str, "IPv6 ", sizeof(str));
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200159 inet_ntop(AF_INET6, pdpa+2, str+5, sizeof(str)-5);
160 return str;
Keith6cee1a12021-09-29 21:00:04 +0200161 case PDP_TYPE_N_IETF_IPv4v6:
162 if (len < 2 + 20)
163 break;
164 if (return_ipv6) {
165 /* The IPv6 token, (rightmost four fields) is a duplicate of
166 * the site prefix + subnetID (leftmost fields) in pdpa here */
167 osmo_strlcpy(str, "IPv6 ", sizeof(str));
168 inet_ntop(AF_INET6, pdpa+6, str+5, sizeof(str)-5);
169 return str;
170 }
171 osmo_strlcpy(str, "IPv4 ", sizeof(str));
172 inet_ntop(AF_INET, pdpa+2, str+5, sizeof(str)-5);
173 return str;
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200174 default:
175 break;
176 }
177 break;
178 case PDP_TYPE_ORG_ETSI:
179 if (pdpa[1] == PDP_TYPE_N_ETSI_PPP)
180 return "PPP";
181 break;
182 default:
183 break;
184 }
185
186 return "invalid";
187}
188
Harald Welte288be162010-05-01 16:48:27 +0200189static struct cmd_node sgsn_node = {
190 SGSN_NODE,
Harald Welte570ce242012-08-17 13:16:10 +0200191 "%s(config-sgsn)# ",
Harald Welte288be162010-05-01 16:48:27 +0200192 1,
193};
194
Pau Espin Pedrole5c89982021-05-03 18:16:42 +0200195static struct cmd_node mme_node = {
196 MME_NODE,
197 "%s(config-sgsn-mme)# ",
198 1,
199};
200
201static void config_write_mme(struct vty *vty, const struct sgsn_mme_ctx *mme, const char *prefix)
202{
203 struct mme_rim_route *rt;
204
205 vty_out(vty, "%smme %s%s", prefix, mme->name, VTY_NEWLINE);
206
207 vty_out(vty, "%s gtp remote-ip %s%s", prefix, inet_ntoa(mme->remote_addr), VTY_NEWLINE);
208 if (mme->default_route)
209 vty_out(vty, "%s gtp ran-info-relay default%s", prefix, VTY_NEWLINE);
210 llist_for_each_entry(rt, &mme->routes, list) {
211 vty_out(vty, "%s gtp ran-info-relay %s %s %u%s", prefix,
212 osmo_mcc_name(rt->tai.mcc), osmo_mnc_name(rt->tai.mnc, rt->tai.mnc_3_digits),
213 rt->tai.tac, VTY_NEWLINE);
214 }
215}
216
Harald Welte288be162010-05-01 16:48:27 +0200217static int config_write_sgsn(struct vty *vty)
218{
Harald Welte77289c22010-05-18 14:32:29 +0200219 struct sgsn_ggsn_ctx *gctx;
Harald Welte7f6da482013-03-19 11:00:13 +0100220 struct imsi_acl_entry *acl;
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100221 struct apn_ctx *actx;
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800222 struct ares_addr_node *server;
Pau Espin Pedrole5c89982021-05-03 18:16:42 +0200223 struct sgsn_mme_ctx *mme;
Eric2f898262021-05-19 18:57:50 +0200224 int i;
Harald Welte288be162010-05-01 16:48:27 +0200225
226 vty_out(vty, "sgsn%s", VTY_NEWLINE);
227
Keithc70e8382020-10-19 22:24:48 +0200228 vty_out(vty, " gtp state-dir %s%s",
229 g_cfg->gtp_statedir, VTY_NEWLINE);
Harald Weltee300d002010-06-02 12:41:34 +0200230 vty_out(vty, " gtp local-ip %s%s",
231 inet_ntoa(g_cfg->gtp_listenaddr.sin_addr), VTY_NEWLINE);
232
Harald Welted193cb32010-05-17 22:58:03 +0200233 llist_for_each_entry(gctx, &sgsn_ggsn_ctxts, list) {
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800234 if (gctx->id == UINT32_MAX)
235 continue;
236
Harald Welteff3bde82010-05-19 15:09:09 +0200237 vty_out(vty, " ggsn %u remote-ip %s%s", gctx->id,
Harald Welted193cb32010-05-17 22:58:03 +0200238 inet_ntoa(gctx->remote_addr), VTY_NEWLINE);
Harald Welteff3bde82010-05-19 15:09:09 +0200239 vty_out(vty, " ggsn %u gtp-version %u%s", gctx->id,
Harald Welted193cb32010-05-17 22:58:03 +0200240 gctx->gtp_version, VTY_NEWLINE);
Pau Espin Pedrolaa89f5d2019-08-28 16:08:45 +0200241 if (gctx->echo_interval)
242 vty_out(vty, " ggsn %u echo-interval %u%s",
Pau Espin Pedrolfa120102018-07-09 20:37:47 +0200243 gctx->id, gctx->echo_interval, VTY_NEWLINE);
Pau Espin Pedrola83850c2018-07-10 12:43:59 +0200244 else
245 vty_out(vty, " ggsn %u no echo-interval%s",
246 gctx->id, VTY_NEWLINE);
Harald Welte288be162010-05-01 16:48:27 +0200247 }
248
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800249 if (sgsn->cfg.dynamic_lookup)
250 vty_out(vty, " ggsn dynamic%s", VTY_NEWLINE);
251
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800252 for (server = sgsn->ares_servers; server; server = server->next)
253 vty_out(vty, " grx-dns-add %s%s", inet_ntoa(server->addr.addr4), VTY_NEWLINE);
254
Neels Hofmeyr340a7e92022-03-07 15:37:24 +0100255 if (g_cfg->gea_encryption_mask != 0) {
Eric2f898262021-05-19 18:57:50 +0200256 vty_out(vty, " encryption gea");
257
258 for (i = 0; i < _GPRS_ALGO_NUM; i++)
Neels Hofmeyr340a7e92022-03-07 15:37:24 +0100259 if (g_cfg->gea_encryption_mask >> i & 1)
Eric2f898262021-05-19 18:57:50 +0200260 vty_out(vty, " %u", i);
261
262 vty_out(vty, "%s", VTY_NEWLINE);
263 }
Stefan Sperling88220092018-12-11 14:42:00 +0100264 if (g_cfg->sgsn_ipa_name)
265 vty_out(vty, " gsup ipa-name %s%s", g_cfg->sgsn_ipa_name, VTY_NEWLINE);
Jacob Erlbeck39f040d2014-12-18 12:46:47 +0100266 if (g_cfg->gsup_server_addr.sin_addr.s_addr)
267 vty_out(vty, " gsup remote-ip %s%s",
268 inet_ntoa(g_cfg->gsup_server_addr.sin_addr), VTY_NEWLINE);
269 if (g_cfg->gsup_server_port)
270 vty_out(vty, " gsup remote-port %d%s",
271 g_cfg->gsup_server_port, VTY_NEWLINE);
Pau Espin Pedrold1463bc2019-06-13 19:03:25 +0200272 if (g_cfg->auth_policy == SGSN_AUTH_POLICY_REMOTE && !g_cfg->require_authentication)
273 vty_out(vty, " authentication optional%s", VTY_NEWLINE);
Max176b62a2016-07-04 11:09:07 +0200274 vty_out(vty, " auth-policy %s%s",
275 get_value_string(sgsn_auth_pol_strs, g_cfg->auth_policy),
276 VTY_NEWLINE);
Neels Hofmeyr568a7272015-10-12 11:57:38 +0200277
278 vty_out(vty, " gsup oap-id %d%s",
279 (int)g_cfg->oap.client_id, VTY_NEWLINE);
280 if (g_cfg->oap.secret_k_present != 0)
281 vty_out(vty, " gsup oap-k %s%s",
282 osmo_hexdump_nospc(g_cfg->oap.secret_k, sizeof(g_cfg->oap.secret_k)),
283 VTY_NEWLINE);
284 if (g_cfg->oap.secret_opc_present != 0)
285 vty_out(vty, " gsup oap-opc %s%s",
286 osmo_hexdump_nospc(g_cfg->oap.secret_opc, sizeof(g_cfg->oap.secret_opc)),
287 VTY_NEWLINE);
288
Harald Welte7f6da482013-03-19 11:00:13 +0100289 llist_for_each_entry(acl, &g_cfg->imsi_acl, list)
290 vty_out(vty, " imsi-acl add %s%s", acl->imsi, VTY_NEWLINE);
291
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100292 if (llist_empty(&sgsn_apn_ctxts))
293 vty_out(vty, " ! apn * ggsn 0%s", VTY_NEWLINE);
294 llist_for_each_entry(actx, &sgsn_apn_ctxts, list) {
295 if (strlen(actx->imsi_prefix) > 0)
Holger Hans Peter Freytherb7ae0b32015-05-29 15:11:55 +0200296 vty_out(vty, " apn %s imsi-prefix %s ggsn %u%s",
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100297 actx->name, actx->imsi_prefix, actx->ggsn->id,
298 VTY_NEWLINE);
299 else
Holger Hans Peter Freytherb7ae0b32015-05-29 15:11:55 +0200300 vty_out(vty, " apn %s ggsn %u%s", actx->name,
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100301 actx->ggsn->id, VTY_NEWLINE);
302 }
303
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +0200304 if (g_cfg->cdr.filename)
305 vty_out(vty, " cdr filename %s%s", g_cfg->cdr.filename, VTY_NEWLINE);
306 else
307 vty_out(vty, " no cdr filename%s", VTY_NEWLINE);
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +0100308 if (g_cfg->cdr.trap)
309 vty_out(vty, " cdr trap%s", VTY_NEWLINE);
310 else
311 vty_out(vty, " no cdr trap%s", VTY_NEWLINE);
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +0200312 vty_out(vty, " cdr interval %d%s", g_cfg->cdr.interval, VTY_NEWLINE);
313
Pau Espin Pedrola299d652019-08-14 19:11:10 +0200314 osmo_tdef_vty_write(vty, g_cfg->T_defs, " timer ");
Harald Welte94508822015-08-15 19:08:21 +0200315
Philippf1f34362016-08-26 17:00:21 +0200316 if (g_cfg->pcomp_rfc1144.active) {
317 vty_out(vty, " compression rfc1144 active slots %d%s",
318 g_cfg->pcomp_rfc1144.s01 + 1, VTY_NEWLINE);
319 } else if (g_cfg->pcomp_rfc1144.passive) {
320 vty_out(vty, " compression rfc1144 passive%s", VTY_NEWLINE);
321 } else
322 vty_out(vty, " no compression rfc1144%s", VTY_NEWLINE);
323
Philipp73f83d52016-09-02 13:38:01 +0200324 if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 1) {
325 vty_out(vty,
326 " compression v42bis active direction sgsn codewords %d strlen %d%s",
327 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
328 VTY_NEWLINE);
329 } else if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 2) {
330 vty_out(vty,
331 " compression v42bis active direction ms codewords %d strlen %d%s",
332 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
333 VTY_NEWLINE);
334 } else if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 3) {
335 vty_out(vty,
336 " compression v42bis active direction both codewords %d strlen %d%s",
337 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
338 VTY_NEWLINE);
339 } else if (g_cfg->dcomp_v42bis.passive) {
340 vty_out(vty, " compression v42bis passive%s", VTY_NEWLINE);
341 } else
342 vty_out(vty, " no compression v42bis%s", VTY_NEWLINE);
343
Pau Espin Pedrole5c89982021-05-03 18:16:42 +0200344 llist_for_each_entry(mme, &sgsn->mme_list, list) {
345 config_write_mme(vty, mme, " ");
346 }
347
Neels Hofmeyr2188a772016-05-20 21:59:55 +0200348#ifdef BUILD_IU
Pau Espin Pedrol2c908992019-08-19 19:06:06 +0200349 vty_out(vty, " cs7-instance-iu %u%s", g_cfg->iu.cs7_instance,
350 VTY_NEWLINE);
Neels Hofmeyra7a39472017-07-05 15:19:52 +0200351 ranap_iu_vty_config_write(vty, " ");
Neels Hofmeyr2188a772016-05-20 21:59:55 +0200352#endif
353
Harald Welte288be162010-05-01 16:48:27 +0200354 return CMD_SUCCESS;
355}
356
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100357#define SGSN_STR "Configure the SGSN\n"
358#define GGSN_STR "Configure the GGSN information\n"
Harald Weltee300d002010-06-02 12:41:34 +0200359
360DEFUN(cfg_sgsn, cfg_sgsn_cmd,
361 "sgsn",
362 SGSN_STR)
Harald Welte288be162010-05-01 16:48:27 +0200363{
364 vty->node = SGSN_NODE;
365 return CMD_SUCCESS;
366}
367
Keithc70e8382020-10-19 22:24:48 +0200368DEFUN(cfg_sgsn_state_dir, cfg_sgsn_state_dir_cmd,
369 "gtp state-dir PATH",
370 "GTP Parameters\n"
371 "Set the directory for the GTP State file\n"
372 "Local Directory\n")
373{
374 osmo_talloc_replace_string(sgsn, &sgsn->cfg.gtp_statedir, argv[0]);
375
376 return CMD_SUCCESS;
377}
378
Harald Weltee300d002010-06-02 12:41:34 +0200379DEFUN(cfg_sgsn_bind_addr, cfg_sgsn_bind_addr_cmd,
380 "gtp local-ip A.B.C.D",
381 "GTP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100382 "Set the IP address for the local GTP bind for the Gp interface (towards the GGSNs)."
383 " Note: in case you would like to run the GGSN on the same machine as the SGSN, you can not run"
384 " both on the same IP address, since both sides are specified to use the same GTP port numbers"
385 " (" OSMO_STRINGIFY_VAL(GTP1C_PORT) " and " OSMO_STRINGIFY_VAL(GTP1U_PORT) ")."
386 " For example, you could use 127.0.0.1 for the SGSN and 127.0.0.2 for the GGSN in such"
387 " situations.\n"
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100388 "IPv4 Address\n")
Harald Weltee300d002010-06-02 12:41:34 +0200389{
390 inet_aton(argv[0], &g_cfg->gtp_listenaddr.sin_addr);
391
392 return CMD_SUCCESS;
393}
394
Harald Welted193cb32010-05-17 22:58:03 +0200395DEFUN(cfg_ggsn_remote_ip, cfg_ggsn_remote_ip_cmd,
396 "ggsn <0-255> remote-ip A.B.C.D",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100397 GGSN_STR "GGSN Number\n"
398 "Configure this static GGSN to use the specified remote IP address.\n"
399 "IPv4 Address\n")
Harald Welted193cb32010-05-17 22:58:03 +0200400{
401 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200402 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welte288be162010-05-01 16:48:27 +0200403
Harald Welted193cb32010-05-17 22:58:03 +0200404 inet_aton(argv[1], &ggc->remote_addr);
Harald Welte288be162010-05-01 16:48:27 +0200405
Harald Welted193cb32010-05-17 22:58:03 +0200406 return CMD_SUCCESS;
407}
408
409#if 0
410DEFUN(cfg_ggsn_remote_port, cfg_ggsn_remote_port_cmd,
411 "ggsn <0-255> remote-port <0-65535>",
412 "")
413{
414 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200415 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welted193cb32010-05-17 22:58:03 +0200416 uint16_t port = atoi(argv[1]);
417
418}
419#endif
420
421DEFUN(cfg_ggsn_gtp_version, cfg_ggsn_gtp_version_cmd,
422 "ggsn <0-255> gtp-version (0|1)",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100423 GGSN_STR "GGSN Number\n" "GTP Version\n"
424 "Version 0\n" "Version 1\n")
Harald Welted193cb32010-05-17 22:58:03 +0200425{
426 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200427 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welted193cb32010-05-17 22:58:03 +0200428
429 if (atoi(argv[1]))
430 ggc->gtp_version = 1;
431 else
432 ggc->gtp_version = 0;
433
434 return CMD_SUCCESS;
435}
436
Pau Espin Pedrolfa120102018-07-09 20:37:47 +0200437/* Seee 3GPP TS 29.060 section 7.2.1 */
438DEFUN(cfg_ggsn_echo_interval, cfg_ggsn_echo_interval_cmd,
439 "ggsn <0-255> echo-interval <1-36000>",
440 GGSN_STR "GGSN Number\n"
441 "Send an echo request to this static GGSN every interval.\n"
442 "Interval between echo requests in seconds.\n")
443{
444 uint32_t id = atoi(argv[0]);
445 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
446
447 ggc->echo_interval = atoi(argv[1]);
448
449 if (ggc->echo_interval < 60)
Pau Espin Pedrolba2e5002019-05-27 17:35:32 +0200450 vty_out(vty, "%% 3GPP TS 29.060 section 7.2.1 states interval should " \
Pau Espin Pedrolfa120102018-07-09 20:37:47 +0200451 "not be lower than 60 seconds, use this value for " \
452 "testing purposes only!%s", VTY_NEWLINE);
453
Alexander Couzens176a4d22018-09-18 20:07:37 +0200454 sgsn_ggsn_ctx_check_echo_timer(ggc);
Pau Espin Pedrolfa120102018-07-09 20:37:47 +0200455 return CMD_SUCCESS;
456}
457
Pau Espin Pedrola83850c2018-07-10 12:43:59 +0200458DEFUN(cfg_ggsn_no_echo_interval, cfg_ggsn_no_echo_interval_cmd,
459 "ggsn <0-255> no echo-interval",
460 GGSN_STR "GGSN Number\n"
461 NO_STR "Send an echo request to this static GGSN every interval.\n")
462{
463 uint32_t id = atoi(argv[0]);
464 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
465
Pau Espin Pedrolaa89f5d2019-08-28 16:08:45 +0200466 ggc->echo_interval = 0;
Alexander Couzens176a4d22018-09-18 20:07:37 +0200467 sgsn_ggsn_ctx_check_echo_timer(ggc);
Pau Espin Pedrola83850c2018-07-10 12:43:59 +0200468
469 return CMD_SUCCESS;
470}
471
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800472DEFUN(cfg_ggsn_dynamic_lookup, cfg_ggsn_dynamic_lookup_cmd,
473 "ggsn dynamic",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100474 GGSN_STR
475 "Enable dynamic resolving of GGSNs based on DNS resolving the APN name like in a GRX-style setup."
476 " Changing this setting requires a restart.\n")
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800477{
478 sgsn->cfg.dynamic_lookup = 1;
479 return CMD_SUCCESS;
480}
481
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800482DEFUN(cfg_grx_ggsn, cfg_grx_ggsn_cmd,
483 "grx-dns-add A.B.C.D",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100484 "Use the specified IP address for DNS-resolving the AP names to GGSN IP addresses\n"
485 "IPv4 address\n")
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800486{
Pau Espin Pedrolb1d1c242018-10-30 17:27:59 +0100487 struct ares_addr_node *node = talloc_zero(tall_sgsn_ctx, struct ares_addr_node);
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800488 node->family = AF_INET;
489 inet_aton(argv[0], &node->addr.addr4);
490
491 node->next = sgsn->ares_servers;
492 sgsn->ares_servers = node;
493 return CMD_SUCCESS;
494}
495
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100496#define APN_STR "Configure the information per APN\n"
497#define APN_GW_STR "The APN gateway name optionally prefixed by '*' (wildcard)\n"
498
499static int add_apn_ggsn_mapping(struct vty *vty, const char *apn_str,
500 const char *imsi_prefix, int ggsn_id)
501{
502 struct apn_ctx *actx;
503 struct sgsn_ggsn_ctx *ggsn;
504
505 ggsn = sgsn_ggsn_ctx_by_id(ggsn_id);
506 if (ggsn == NULL) {
507 vty_out(vty, "%% a GGSN with id %d has not been defined%s",
508 ggsn_id, VTY_NEWLINE);
509 return CMD_WARNING;
510 }
511
512 actx = sgsn_apn_ctx_find_alloc(apn_str, imsi_prefix);
513 if (!actx) {
514 vty_out(vty, "%% unable to create APN context for %s/%s%s",
515 apn_str, imsi_prefix, VTY_NEWLINE);
516 return CMD_WARNING;
517 }
518
519 actx->ggsn = ggsn;
520
521 return CMD_SUCCESS;
522}
523
Harald Welted193cb32010-05-17 22:58:03 +0200524DEFUN(cfg_apn_ggsn, cfg_apn_ggsn_cmd,
525 "apn APNAME ggsn <0-255>",
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100526 APN_STR APN_GW_STR
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100527 "Select the GGSN to use for the given APN gateway prefix\n"
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100528 "The GGSN id")
Harald Welted193cb32010-05-17 22:58:03 +0200529{
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100530
531 return add_apn_ggsn_mapping(vty, argv[0], "", atoi(argv[1]));
Harald Welted193cb32010-05-17 22:58:03 +0200532}
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100533
534DEFUN(cfg_apn_imsi_ggsn, cfg_apn_imsi_ggsn_cmd,
535 "apn APNAME imsi-prefix IMSIPRE ggsn <0-255>",
536 APN_STR APN_GW_STR
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100537 "Select the GGSN to use for the given APN gateway prefix if and only if the IMSI matches the"
538 " given prefix.\n"
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100539 "An IMSI prefix\n"
540 "Select the GGSN to use when APN gateway and IMSI prefix match\n"
541 "The GGSN id")
542{
543
544 return add_apn_ggsn_mapping(vty, argv[0], argv[1], atoi(argv[2]));
545}
Harald Welted193cb32010-05-17 22:58:03 +0200546
Maxc005db72017-10-27 18:43:29 +0200547char *sgsn_gtp_ntoa(struct ul16_t *ul)
Harald Welte471ac7d2016-12-15 19:48:58 +0100548{
Max8492c202017-12-05 17:28:15 +0100549 struct in_addr ia;
550
551 if (gsna2in_addr(&ia, ul) != 0)
Harald Welte471ac7d2016-12-15 19:48:58 +0100552 return "UNKNOWN";
Max8492c202017-12-05 17:28:15 +0100553
554 return inet_ntoa(ia);
Harald Welte471ac7d2016-12-15 19:48:58 +0100555}
556
Harald Welted193cb32010-05-17 22:58:03 +0200557static void vty_dump_pdp(struct vty *vty, const char *pfx,
558 struct sgsn_pdp_ctx *pdp)
559{
Jacob Erlbeck99985b52014-10-13 10:32:00 +0200560 const char *imsi = pdp->mm ? pdp->mm->imsi : "(detaching)";
Harald Welte471ac7d2016-12-15 19:48:58 +0100561 vty_out(vty, "%sPDP Context IMSI: %s, SAPI: %u, NSAPI: %u, TI: %u%s",
562 pfx, imsi, pdp->sapi, pdp->nsapi, pdp->ti, VTY_NEWLINE);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200563 if (pdp->lib) {
Max7933d962017-10-19 16:52:30 +0200564 char apnbuf[APN_MAXLEN + 1];
Harald Weltedfbd2c82017-08-13 00:56:45 +0200565 vty_out(vty, "%s APN: %s%s", pfx,
Max7933d962017-10-19 16:52:30 +0200566 osmo_apn_to_str(apnbuf, pdp->lib->apn_use.v, pdp->lib->apn_use.l),
Harald Weltedfbd2c82017-08-13 00:56:45 +0200567 VTY_NEWLINE);
568 vty_out(vty, "%s PDP Address: %s%s", pfx,
Keith6cee1a12021-09-29 21:00:04 +0200569 gprs_pdpaddr2str(pdp->lib->eua.v, pdp->lib->eua.l, false),
Harald Weltedfbd2c82017-08-13 00:56:45 +0200570 VTY_NEWLINE);
Keith6cee1a12021-09-29 21:00:04 +0200571 if (pdp->lib->eua.v[1] == PDP_TYPE_N_IETF_IPv4v6) {
572 vty_out(vty, "%s PDP Address: %s%s", pfx,
573 gprs_pdpaddr2str(pdp->lib->eua.v, pdp->lib->eua.l, true),
574 VTY_NEWLINE);
575 }
Maxb24af2b2017-12-05 17:54:42 +0100576 vty_out(vty, "%s GTPv%d Local Control(%s / TEIC: 0x%08x) ", pfx, pdp->lib->version,
Maxc005db72017-10-27 18:43:29 +0200577 sgsn_gtp_ntoa(&pdp->lib->gsnlc), pdp->lib->teic_own);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200578 vty_out(vty, "Data(%s / TEID: 0x%08x)%s",
Maxc005db72017-10-27 18:43:29 +0200579 sgsn_gtp_ntoa(&pdp->lib->gsnlu), pdp->lib->teid_own, VTY_NEWLINE);
Maxb24af2b2017-12-05 17:54:42 +0100580 vty_out(vty, "%s GTPv%d Remote Control(%s / TEIC: 0x%08x) ", pfx, pdp->lib->version,
Maxc005db72017-10-27 18:43:29 +0200581 sgsn_gtp_ntoa(&pdp->lib->gsnrc), pdp->lib->teic_gn);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200582 vty_out(vty, "Data(%s / TEID: 0x%08x)%s",
Maxc005db72017-10-27 18:43:29 +0200583 sgsn_gtp_ntoa(&pdp->lib->gsnru), pdp->lib->teid_gn, VTY_NEWLINE);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200584 }
Harald Welte471ac7d2016-12-15 19:48:58 +0100585
Harald Welteefbdee92010-06-10 00:20:12 +0200586 vty_out_rate_ctr_group(vty, " ", pdp->ctrg);
Harald Welted193cb32010-05-17 22:58:03 +0200587}
588
589static void vty_dump_mmctx(struct vty *vty, const char *pfx,
590 struct sgsn_mm_ctx *mm, int pdp)
591{
Pau Espin Pedrol9119d502019-08-30 17:48:10 +0200592 uint32_t id = 0;
Pau Espin Pedrolfd815bb2019-08-30 18:32:42 +0200593 const char *mm_state_name = NULL;
Pau Espin Pedrol9119d502019-08-30 17:48:10 +0200594
595 switch(mm->ran_type) {
596 case MM_CTX_T_UTRAN_Iu:
597#if BUILD_IU
598 id = mm->iu.ue_ctx->conn_id;
Pau Espin Pedrolfd815bb2019-08-30 18:32:42 +0200599 mm_state_name = osmo_fsm_inst_state_name(mm->iu.mm_state_fsm);
Pau Espin Pedrol9119d502019-08-30 17:48:10 +0200600#endif
601 break;
602 case MM_CTX_T_GERAN_Gb:
603 id = mm->gb.tlli;
Pau Espin Pedrolfd815bb2019-08-30 18:32:42 +0200604 mm_state_name = osmo_fsm_inst_state_name(mm->gb.mm_state_fsm);
Pau Espin Pedrol9119d502019-08-30 17:48:10 +0200605 break;
606 }
607
Harald Welted193cb32010-05-17 22:58:03 +0200608 vty_out(vty, "%sMM Context for IMSI %s, IMEI %s, P-TMSI %08x%s",
609 pfx, mm->imsi, mm->imei, mm->p_tmsi, VTY_NEWLINE);
Holger Hans Peter Freyther8ee13e22015-05-18 10:00:03 +0200610 vty_out(vty, "%s MSISDN: %s, TLLI: %08x%s HLR: %s",
Pau Espin Pedrol9119d502019-08-30 17:48:10 +0200611 pfx, mm->msisdn, id, mm->hlr, VTY_NEWLINE);
Pau Espin Pedrolfd815bb2019-08-30 18:32:42 +0200612 vty_out(vty, "%s GMM State: %s, Routeing Area: %s, Cell ID: %u%s",
Pau Espin Pedrol31c46572019-09-02 16:45:27 +0200613 pfx, osmo_fsm_inst_state_name(mm->gmm_fsm),
Neels Hofmeyr10719b72018-02-21 00:39:36 +0100614 osmo_rai_name(&mm->ra), mm->gb.cell_id, VTY_NEWLINE);
Pau Espin Pedrolfd815bb2019-08-30 18:32:42 +0200615 vty_out(vty, "%s MM State: %s, RAN Type: %s%s", pfx, mm_state_name,
616 get_value_string(sgsn_ran_type_names, mm->ran_type), VTY_NEWLINE);
Harald Welted193cb32010-05-17 22:58:03 +0200617
Pau Espin Pedrol3b848bd2019-08-30 18:06:35 +0200618 vty_out_rate_ctr_group(vty, " ", mm->ctrg);
Harald Welte8acd88f2010-05-18 10:57:45 +0200619
Harald Welted193cb32010-05-17 22:58:03 +0200620 if (pdp) {
621 struct sgsn_pdp_ctx *pdp;
622
623 llist_for_each_entry(pdp, &mm->pdp_list, list)
624 vty_dump_pdp(vty, " ", pdp);
625 }
626}
627
628DEFUN(show_sgsn, show_sgsn_cmd, "show sgsn",
629 SHOW_STR "Display information about the SGSN")
630{
Jacob Erlbeck80547992014-12-19 19:19:46 +0100631 if (sgsn->gsup_client) {
632 struct ipa_client_conn *link = sgsn->gsup_client->link;
633 vty_out(vty,
634 " Remote authorization: %sconnected to %s:%d via GSUP%s",
635 sgsn->gsup_client->is_connected ? "" : "not ",
636 link->addr, link->port,
637 VTY_NEWLINE);
638 }
Maxbaabc682017-10-20 13:39:57 +0200639 if (sgsn->gsn)
640 vty_out(vty, " GSN: signalling %s, user traffic %s%s",
641 inet_ntoa(sgsn->gsn->gsnc), inet_ntoa(sgsn->gsn->gsnu), VTY_NEWLINE);
642
Harald Welted193cb32010-05-17 22:58:03 +0200643 /* FIXME: statistics */
644 return CMD_SUCCESS;
645}
646
647#define MMCTX_STR "MM Context\n"
648#define INCLUDE_PDP_STR "Include PDP Context Information\n"
649
650#if 0
651DEFUN(show_mmctx_tlli, show_mmctx_tlli_cmd,
652 "show mm-context tlli HEX [pdp]",
653 SHOW_STR MMCTX_STR "Identify by TLLI\n" "TLLI\n" INCLUDE_PDP_STR)
654{
655 uint32_t tlli;
656 struct sgsn_mm_ctx *mm;
657
658 tlli = strtoul(argv[0], NULL, 16);
659 mm = sgsn_mm_ctx_by_tlli(tlli);
660 if (!mm) {
661 vty_out(vty, "No MM context for TLLI %08x%s",
662 tlli, VTY_NEWLINE);
663 return CMD_WARNING;
664 }
665 vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
666 return CMD_SUCCESS;
667}
668#endif
669
670DEFUN(swow_mmctx_imsi, show_mmctx_imsi_cmd,
671 "show mm-context imsi IMSI [pdp]",
672 SHOW_STR MMCTX_STR "Identify by IMSI\n" "IMSI of the MM Context\n"
673 INCLUDE_PDP_STR)
674{
675 struct sgsn_mm_ctx *mm;
676
677 mm = sgsn_mm_ctx_by_imsi(argv[0]);
678 if (!mm) {
679 vty_out(vty, "No MM context for IMSI %s%s",
680 argv[0], VTY_NEWLINE);
681 return CMD_WARNING;
682 }
Keithc12c1a62021-05-20 04:41:01 +0200683 vty_dump_mmctx(vty, "", mm, (argc > 1) ? 1 : 0);
Harald Welted193cb32010-05-17 22:58:03 +0200684 return CMD_SUCCESS;
685}
686
687DEFUN(swow_mmctx_all, show_mmctx_all_cmd,
688 "show mm-context all [pdp]",
689 SHOW_STR MMCTX_STR "All MM Contexts\n" INCLUDE_PDP_STR)
690{
691 struct sgsn_mm_ctx *mm;
Harald Welted193cb32010-05-17 22:58:03 +0200692 llist_for_each_entry(mm, &sgsn_mm_ctxts, list)
Keithc12c1a62021-05-20 04:41:01 +0200693 vty_dump_mmctx(vty, "", mm, (argc > 0) ? 1 : 0);
Harald Welted193cb32010-05-17 22:58:03 +0200694
695 return CMD_SUCCESS;
696}
697
Harald Welted193cb32010-05-17 22:58:03 +0200698DEFUN(show_pdpctx_all, show_pdpctx_all_cmd,
699 "show pdp-context all",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100700 SHOW_STR "Display information on PDP Context\n" "Show everything\n")
Harald Welted193cb32010-05-17 22:58:03 +0200701{
702 struct sgsn_pdp_ctx *pdp;
703
704 llist_for_each_entry(pdp, &sgsn_pdp_ctxts, g_list)
705 vty_dump_pdp(vty, "", pdp);
706
707 return CMD_SUCCESS;
708}
Harald Welte288be162010-05-01 16:48:27 +0200709
Harald Welte7f6da482013-03-19 11:00:13 +0100710
711DEFUN(imsi_acl, cfg_imsi_acl_cmd,
712 "imsi-acl (add|del) IMSI",
713 "Access Control List of foreign IMSIs\n"
714 "Add IMSI to ACL\n"
715 "Remove IMSI from ACL\n"
716 "IMSI of subscriber\n")
717{
Maxef38b4c2018-11-20 10:25:53 +0100718 char imsi_sanitized[GSM23003_IMSI_MAX_DIGITS + 1];
Harald Welte7f6da482013-03-19 11:00:13 +0100719 const char *op = argv[0];
Philipp Maier6ee49d82017-02-28 16:53:07 +0100720 const char *imsi = imsi_sanitized;
Maxf4fa6952018-01-15 12:12:51 +0100721 size_t len = strnlen(argv[1], GSM23003_IMSI_MAX_DIGITS + 1);
Harald Welte7f6da482013-03-19 11:00:13 +0100722 int rc;
723
Maxef38b4c2018-11-20 10:25:53 +0100724 memset(imsi_sanitized, '0', GSM23003_IMSI_MAX_DIGITS);
725 imsi_sanitized[GSM23003_IMSI_MAX_DIGITS] = '\0';
726
Philipp Maier6ee49d82017-02-28 16:53:07 +0100727 /* Sanitize IMSI */
Maxf4fa6952018-01-15 12:12:51 +0100728 if (len > GSM23003_IMSI_MAX_DIGITS) {
729 vty_out(vty, "%% IMSI (%s) too long (max %u digits) -- ignored!%s",
730 argv[1], GSM23003_IMSI_MAX_DIGITS, VTY_NEWLINE);
Philipp Maier6ee49d82017-02-28 16:53:07 +0100731 return CMD_WARNING;
732 }
Maxf4fa6952018-01-15 12:12:51 +0100733
734 osmo_strlcpy(imsi_sanitized + GSM23003_IMSI_MAX_DIGITS - len, argv[1],
735 sizeof(imsi_sanitized) - (GSM23003_IMSI_MAX_DIGITS - len));
Philipp Maier6ee49d82017-02-28 16:53:07 +0100736
Harald Welte7f6da482013-03-19 11:00:13 +0100737 if (!strcmp(op, "add"))
Jacob Erlbeck3b5d4072014-10-24 15:11:03 +0200738 rc = sgsn_acl_add(imsi, g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +0100739 else
Jacob Erlbeck3b5d4072014-10-24 15:11:03 +0200740 rc = sgsn_acl_del(imsi, g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +0100741
742 if (rc < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100743 vty_out(vty, "%% unable to %s ACL%s", op, VTY_NEWLINE);
Harald Welte7f6da482013-03-19 11:00:13 +0100744 return CMD_WARNING;
745 }
746
747 return CMD_SUCCESS;
748}
749
Eric2f898262021-05-19 18:57:50 +0200750DEFUN_DEPRECATED(cfg_encrypt, cfg_encrypt_cmd,
Max93408ae2016-06-28 14:10:16 +0200751 "encryption (GEA0|GEA1|GEA2|GEA3|GEA4)",
752 "Set encryption algorithm for SGSN\n"
753 "Use GEA0 (no encryption)\n"
754 "Use GEA1\nUse GEA2\nUse GEA3\nUse GEA4\n")
755{
Max93408ae2016-06-28 14:10:16 +0200756 enum gprs_ciph_algo c = get_string_value(gprs_cipher_names, argv[0]);
Eric2f898262021-05-19 18:57:50 +0200757
758 if (strcmp(argv[0], "gea") == 0)
759 return CMD_SUCCESS;
760
Max086067f2017-05-02 13:03:28 +0200761 if (c != GPRS_ALGO_GEA0) {
Eric2f898262021-05-19 18:57:50 +0200762 if (gprs_cipher_supported(c) <= 0) {
Max086067f2017-05-02 13:03:28 +0200763 vty_out(vty, "%% cipher %s is unsupported in current version%s", argv[0], VTY_NEWLINE);
764 return CMD_WARNING;
765 }
766
767 if (!g_cfg->require_authentication) {
768 vty_out(vty, "%% unable to use encryption %s without authentication: please adjust auth-policy%s",
769 argv[0], VTY_NEWLINE);
770 return CMD_WARNING;
771 }
Max93408ae2016-06-28 14:10:16 +0200772 }
773
Neels Hofmeyr340a7e92022-03-07 15:37:24 +0100774 g_cfg->gea_encryption_mask |= (1 << c);
Eric2f898262021-05-19 18:57:50 +0200775
776 return CMD_SUCCESS;
777}
778
Neels Hofmeyr3c7656a2022-03-07 15:38:59 +0100779#define ENCRYPTION_STR "Set encryption algorithms for SGSN\n"
780
Eric2f898262021-05-19 18:57:50 +0200781DEFUN(cfg_encrypt2, cfg_encrypt2_cmd,
782 "encryption gea <0-4> [<0-4>] [<0-4>] [<0-4>] [<0-4>]",
Neels Hofmeyr3c7656a2022-03-07 15:38:59 +0100783 ENCRYPTION_STR
Eric2f898262021-05-19 18:57:50 +0200784 "GPRS Encryption Algorithm\n"
785 "GEAn Algorithm Number\n"
786 "GEAn Algorithm Number\n"
787 "GEAn Algorithm Number\n"
788 "GEAn Algorithm Number\n"
789 "GEAn Algorithm Number\n")
790{
791 int i = 0;
792
Neels Hofmeyr340a7e92022-03-07 15:37:24 +0100793 g_cfg->gea_encryption_mask = 0;
Eric2f898262021-05-19 18:57:50 +0200794 for (i = 0; i < argc; i++)
Neels Hofmeyr340a7e92022-03-07 15:37:24 +0100795 g_cfg->gea_encryption_mask |= (1 << atoi(argv[i]));
Eric2f898262021-05-19 18:57:50 +0200796
797 for (i = 0; i < _GPRS_ALGO_NUM; i++) {
Neels Hofmeyr340a7e92022-03-07 15:37:24 +0100798 if (g_cfg->gea_encryption_mask >> i & 1) {
Eric2f898262021-05-19 18:57:50 +0200799
800 if (i == GPRS_ALGO_GEA0)
801 continue;
802
803 if (gprs_cipher_supported(i) <= 0) {
804 vty_out(vty, "%% cipher %d is unsupported in current version%s", i, VTY_NEWLINE);
805 return CMD_ERR_INCOMPLETE;
806 }
807
808 if (!g_cfg->require_authentication) {
809 vty_out(vty, "%% unable to use encryption %s without authentication: please adjust auth-policy%s",
810 argv[i], VTY_NEWLINE);
811 return CMD_ERR_INCOMPLETE;
812 }
813
814 }
815 }
Max93408ae2016-06-28 14:10:16 +0200816
817 return CMD_SUCCESS;
818}
819
Vadim Yanitskiy794f4462019-05-27 05:39:06 +0700820DEFUN(cfg_authentication, cfg_authentication_cmd,
821 "authentication (optional|required)",
Pau Espin Pedrold1463bc2019-06-13 19:03:25 +0200822 "Whether to enforce MS authentication in GERAN (only with auth-policy remote)\n"
823 "Allow MS to attach via GERAN without authentication (default and only possible value for non-remote auth-policy)\n"
824 "Always require authentication (only available for auth-policy remote, default with that auth-policy)\n")
Vadim Yanitskiy794f4462019-05-27 05:39:06 +0700825{
826 int required = (argv[0][0] == 'r');
827
828 if (vty->type != VTY_FILE) {
829 if (g_cfg->auth_policy != SGSN_AUTH_POLICY_REMOTE && required) {
830 vty_out(vty, "%% Authentication is not possible without HLR, "
831 "consider setting 'auth-policy' to 'remote'%s",
832 VTY_NEWLINE);
833 return CMD_WARNING;
834 }
835 }
836
837 g_cfg->require_authentication = required;
838 return CMD_SUCCESS;
839}
840
Neels Hofmeyr3c7656a2022-03-07 15:38:59 +0100841DEFUN(cfg_encryption_uea, cfg_encryption_uea_cmd,
842 "encryption uea <0-2> [<0-2>] [<0-2>]",
843 ENCRYPTION_STR
844 "UTRAN (3G) encryption algorithms to allow: 0 = UEA0 (no encryption), 1 = UEA1, 2 = UEA2.\n"
845 "UEAn Algorithm Number\n"
846 "UEAn Algorithm Number\n"
847 "UEAn Algorithm Number\n")
848{
849 unsigned int i;
850
851 g_cfg->uea_encryption_mask = 0;
852 for (i = 0; i < argc; i++)
853 g_cfg->uea_encryption_mask |= (1 << atoi(argv[i]));
854
855 return CMD_SUCCESS;
856}
857
Harald Welte3dfb5492013-03-19 11:48:54 +0100858DEFUN(cfg_auth_policy, cfg_auth_policy_cmd,
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100859 "auth-policy (accept-all|closed|acl-only|remote)",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100860 "Configure the Authorization policy of the SGSN. This setting determines which subscribers are"
861 " permitted to register to the network.\n"
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100862 "Accept all IMSIs (DANGEROUS)\n"
863 "Accept only home network subscribers or those in the ACL\n"
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100864 "Accept only subscribers in the ACL\n"
865 "Use remote subscription data only (HLR)\n")
Harald Welte3dfb5492013-03-19 11:48:54 +0100866{
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100867 int val = get_string_value(sgsn_auth_pol_strs, argv[0]);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100868 OSMO_ASSERT(val >= SGSN_AUTH_POLICY_OPEN && val <= SGSN_AUTH_POLICY_REMOTE);
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100869 g_cfg->auth_policy = val;
Jacob Erlbeck771573c2014-12-19 18:08:48 +0100870 g_cfg->require_update_location = (val == SGSN_AUTH_POLICY_REMOTE);
Harald Welte3dfb5492013-03-19 11:48:54 +0100871
872 return CMD_SUCCESS;
873}
874
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100875/* Subscriber */
Neels Hofmeyr396f2e62017-09-04 15:13:25 +0200876#include <osmocom/sgsn/gprs_subscriber.h>
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100877
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100878static void subscr_dump_full_vty(struct vty *vty, struct gprs_subscr *gsub, int pending)
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100879{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100880#if 0
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100881 char expire_time[200];
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100882#endif
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100883 struct gsm_auth_tuple *at;
884 int at_idx;
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100885 struct sgsn_subscriber_pdp_data *pdp;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100886
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100887 vty_out(vty, " Authorized: %d%s",
888 gsub->authorized, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100889 vty_out(vty, " LAC: %d/0x%x%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100890 gsub->lac, gsub->lac, VTY_NEWLINE);
891 vty_out(vty, " IMSI: %s%s", gsub->imsi, VTY_NEWLINE);
892 if (gsub->tmsi != GSM_RESERVED_TMSI)
893 vty_out(vty, " TMSI: %08X%s", gsub->tmsi,
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100894 VTY_NEWLINE);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100895 if (gsub->sgsn_data->msisdn_len > 0)
Holger Hans Peter Freytherf7b38262015-04-23 16:58:33 -0400896 vty_out(vty, " MSISDN (BCD): %s%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100897 osmo_hexdump(gsub->sgsn_data->msisdn,
898 gsub->sgsn_data->msisdn_len),
Holger Hans Peter Freytherf7b38262015-04-23 16:58:33 -0400899 VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100900
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100901 if (strlen(gsub->imei) > 0)
902 vty_out(vty, " IMEI: %s%s", gsub->imei, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100903
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100904 for (at_idx = 0; at_idx < ARRAY_SIZE(gsub->sgsn_data->auth_triplets);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100905 at_idx++) {
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100906 at = &gsub->sgsn_data->auth_triplets[at_idx];
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100907 if (at->key_seq == GSM_KEY_SEQ_INVAL)
908 continue;
909
910 vty_out(vty, " A3A8 tuple (used %d times): ",
911 at->use_count);
Harald Welte89837d42016-05-06 23:28:11 +0200912 vty_out(vty, " CKSN: %d, ",
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100913 at->key_seq);
Harald Welte89837d42016-05-06 23:28:11 +0200914 if (at->vec.auth_types & OSMO_AUTH_TYPE_GSM) {
915 vty_out(vty, "RAND: %s, ",
Max34604c22019-02-13 14:11:29 +0100916 osmo_hexdump_nospc(at->vec.rand,
Harald Welte89837d42016-05-06 23:28:11 +0200917 sizeof(at->vec.rand)));
918 vty_out(vty, "SRES: %s, ",
Max34604c22019-02-13 14:11:29 +0100919 osmo_hexdump_nospc(at->vec.sres,
Harald Welte89837d42016-05-06 23:28:11 +0200920 sizeof(at->vec.sres)));
921 vty_out(vty, "Kc: %s%s",
Max34604c22019-02-13 14:11:29 +0100922 osmo_hexdump_nospc(at->vec.kc,
Harald Welte89837d42016-05-06 23:28:11 +0200923 sizeof(at->vec.kc)), VTY_NEWLINE);
924 }
925 if (at->vec.auth_types & OSMO_AUTH_TYPE_UMTS) {
926 vty_out(vty, " AUTN: %s, ",
927 osmo_hexdump(at->vec.autn,
928 sizeof(at->vec.autn)));
929 vty_out(vty, "RES: %s, ",
Max34604c22019-02-13 14:11:29 +0100930 osmo_hexdump_nospc(at->vec.res, at->vec.res_len));
Harald Welte89837d42016-05-06 23:28:11 +0200931 vty_out(vty, "IK: %s, ",
Max34604c22019-02-13 14:11:29 +0100932 osmo_hexdump_nospc(at->vec.ik, sizeof(at->vec.ik)));
Harald Welte89837d42016-05-06 23:28:11 +0200933 vty_out(vty, "CK: %s, ",
Max34604c22019-02-13 14:11:29 +0100934 osmo_hexdump_nospc(at->vec.ck, sizeof(at->vec.ck)));
Harald Welte89837d42016-05-06 23:28:11 +0200935 }
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100936 }
937
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100938 llist_for_each_entry(pdp, &gsub->sgsn_data->pdp_list, list) {
Max34604c22019-02-13 14:11:29 +0100939 vty_out(vty, " PDP info: Id: %d, Type: 0x%04x, APN: '%s'",
940 pdp->context_id, pdp->pdp_type, pdp->apn_str);
941
942 if (pdp->qos_subscribed_len)
943 vty_out(vty, " QoS: %s", osmo_hexdump(pdp->qos_subscribed, pdp->qos_subscribed_len));
944
945 vty_out(vty, "%s", VTY_NEWLINE);
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100946 }
947
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100948#if 0
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100949 /* print the expiration time of a subscriber */
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100950 if (gsub->expire_lu) {
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100951 strftime(expire_time, sizeof(expire_time),
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100952 "%a, %d %b %Y %T %z", localtime(&gsub->expire_lu));
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100953 expire_time[sizeof(expire_time) - 1] = '\0';
954 vty_out(vty, " Expiration Time: %s%s", expire_time, VTY_NEWLINE);
955 }
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100956#endif
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100957
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100958 if (gsub->flags)
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100959 vty_out(vty, " Flags: %s%s%s%s%s%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100960 gsub->flags & GPRS_SUBSCRIBER_FIRST_CONTACT ?
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100961 "FIRST_CONTACT " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100962 gsub->flags & GPRS_SUBSCRIBER_CANCELLED ?
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100963 "CANCELLED " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100964 gsub->flags & GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING ?
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100965 "UPDATE_LOCATION_PENDING " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100966 gsub->flags & GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING ?
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100967 "AUTH_INFO_PENDING " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100968 gsub->flags & GPRS_SUBSCRIBER_ENABLE_PURGE ?
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100969 "ENABLE_PURGE " : "",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100970 VTY_NEWLINE);
971
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100972 vty_out(vty, " Use count: %u%s", gsub->use_count, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100973}
974
Neels Hofmeyr1a9414b2018-09-24 18:14:29 +0200975#define RESET_SGSN_STATE_STR \
976 "Remove all known subscribers, MM contexts and flush BSSGP queues." \
977 " Useful only when running tests against the SGSN\n"
978
Alexander Couzensc503f0a2018-08-07 17:50:04 +0200979DEFUN_HIDDEN(reset_sgsn_state,
980 reset_sgsn_state_cmd,
981 "reset sgsn state",
Neels Hofmeyr1a9414b2018-09-24 18:14:29 +0200982 RESET_SGSN_STATE_STR RESET_SGSN_STATE_STR RESET_SGSN_STATE_STR)
Alexander Couzensc503f0a2018-08-07 17:50:04 +0200983{
984 struct gprs_subscr *subscr, *tmp_subscr;
985 struct sgsn_mm_ctx *mm, *tmp_mm;
986
987 llist_for_each_entry_safe(mm, tmp_mm, &sgsn_mm_ctxts, list)
988 {
989 gsm0408_gprs_access_cancelled(mm, SGSN_ERROR_CAUSE_NONE);
990 }
991 vty_out(vty, "Cancelled MM Ctx. %s", VTY_NEWLINE);
992
993 llist_for_each_entry_safe(subscr, tmp_subscr, gprs_subscribers, entry) {
994 gprs_subscr_get(subscr);
995 gprs_subscr_cancel(subscr);
996 gprs_subscr_put(subscr);
997 }
998 vty_out(vty, "Removed all gprs subscribers.%s", VTY_NEWLINE);
999
1000 bssgp_flush_all_queues();
1001 vty_out(vty, "Flushed all BSSGPs queues.%s", VTY_NEWLINE);
1002
Alexander Couzens35c34942018-09-17 04:39:14 +02001003 gtp_clear_queues(sgsn->gsn);
Alexander Couzensa66f0f22018-09-18 16:09:18 +02001004 vty_out(vty, "Flushed rx & tx queus towards the GGSN.%s", VTY_NEWLINE);
Alexander Couzens35c34942018-09-17 04:39:14 +02001005
Alexander Couzensc503f0a2018-08-07 17:50:04 +02001006 /* remove all queues to bssgp */
1007 return CMD_SUCCESS;
1008}
1009
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001010DEFUN(show_subscr_cache,
1011 show_subscr_cache_cmd,
1012 "show subscriber cache",
1013 SHOW_STR "Show information about subscribers\n"
1014 "Display contents of subscriber cache\n")
1015{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001016 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001017
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001018 llist_for_each_entry(subscr, gprs_subscribers, entry) {
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001019 vty_out(vty, " Subscriber:%s", VTY_NEWLINE);
1020 subscr_dump_full_vty(vty, subscr, 0);
1021 }
1022
1023 return CMD_SUCCESS;
1024}
1025
1026#define UPDATE_SUBSCR_STR "update-subscriber imsi IMSI "
1027#define UPDATE_SUBSCR_HELP "Update subscriber list\n" \
1028 "Use the IMSI to select the subscriber\n" \
1029 "The IMSI\n"
1030
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01001031#define UPDATE_SUBSCR_INSERT_HELP "Insert data into the subscriber record\n"
1032
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01001033DEFUN(update_subscr_insert_auth_triplet, update_subscr_insert_auth_triplet_cmd,
1034 UPDATE_SUBSCR_STR "insert auth-triplet <1-5> sres SRES rand RAND kc KC",
1035 UPDATE_SUBSCR_HELP
1036 UPDATE_SUBSCR_INSERT_HELP
1037 "Update authentication triplet\n"
1038 "Triplet index\n"
1039 "Set SRES value\nSRES value (4 byte) in hex\n"
1040 "Set RAND value\nRAND value (16 byte) in hex\n"
1041 "Set Kc value\nKc value (8 byte) in hex\n")
1042{
1043 const char *imsi = argv[0];
1044 const int cksn = atoi(argv[1]) - 1;
1045 const char *sres_str = argv[2];
1046 const char *rand_str = argv[3];
1047 const char *kc_str = argv[4];
1048 struct gsm_auth_tuple at = {0,};
1049
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001050 struct gprs_subscr *subscr;
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01001051
Jacob Erlbeckd9193432015-01-19 14:11:46 +01001052 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01001053 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +01001054 vty_out(vty, "%% unable get subscriber record for %s%s",
1055 imsi, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01001056 return CMD_WARNING;
1057 }
1058
1059 OSMO_ASSERT(subscr->sgsn_data);
1060
Harald Welte121e9a42016-04-20 13:13:19 +02001061 if (osmo_hexparse(sres_str, &at.vec.sres[0], sizeof(at.vec.sres)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +01001062 vty_out(vty, "%% invalid SRES value '%s'%s",
1063 sres_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01001064 goto failed;
1065 }
Harald Welte121e9a42016-04-20 13:13:19 +02001066 if (osmo_hexparse(rand_str, &at.vec.rand[0], sizeof(at.vec.rand)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +01001067 vty_out(vty, "%% invalid RAND value '%s'%s",
1068 rand_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01001069 goto failed;
1070 }
Harald Welte121e9a42016-04-20 13:13:19 +02001071 if (osmo_hexparse(kc_str, &at.vec.kc[0], sizeof(at.vec.kc)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +01001072 vty_out(vty, "%% invalid Kc value '%s'%s",
1073 kc_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01001074 goto failed;
1075 }
1076 at.key_seq = cksn;
1077
1078 subscr->sgsn_data->auth_triplets[cksn] = at;
1079 subscr->sgsn_data->auth_triplets_updated = 1;
1080
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001081 gprs_subscr_put(subscr);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01001082
1083 return CMD_SUCCESS;
1084
1085failed:
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001086 gprs_subscr_put(subscr);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01001087 return CMD_SUCCESS;
1088}
1089
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001090DEFUN(update_subscr_cancel, update_subscr_cancel_cmd,
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +01001091 UPDATE_SUBSCR_STR "cancel (update-procedure|subscription-withdraw)",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001092 UPDATE_SUBSCR_HELP
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +01001093 "Cancel (remove) subscriber record\n"
1094 "The MS moved to another SGSN\n"
1095 "The subscription is no longer valid\n")
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001096{
1097 const char *imsi = argv[0];
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +01001098 const char *cancel_type = argv[1];
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001099
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001100 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001101
1102 subscr = gprs_subscr_get_by_imsi(imsi);
1103 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +01001104 vty_out(vty, "%% no subscriber record for %s%s",
1105 imsi, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001106 return CMD_WARNING;
1107 }
1108
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +01001109 if (strcmp(cancel_type, "update-procedure") == 0)
1110 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
1111 else
1112 subscr->sgsn_data->error_cause = GMM_CAUSE_IMPL_DETACHED;
1113
Jacob Erlbeck37139e52015-01-23 13:52:55 +01001114 gprs_subscr_cancel(subscr);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001115 gprs_subscr_put(subscr);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001116
1117 return CMD_SUCCESS;
1118}
1119
Jacob Erlbeckd9193432015-01-19 14:11:46 +01001120DEFUN(update_subscr_create, update_subscr_create_cmd,
1121 UPDATE_SUBSCR_STR "create",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001122 UPDATE_SUBSCR_HELP
Jacob Erlbeckd9193432015-01-19 14:11:46 +01001123 "Create a subscriber entry\n")
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001124{
1125 const char *imsi = argv[0];
1126
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001127 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001128
1129 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +01001130 if (subscr) {
1131 vty_out(vty, "%% subscriber record already exists for %s%s",
1132 imsi, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001133 return CMD_WARNING;
1134 }
1135
Jacob Erlbeckd9193432015-01-19 14:11:46 +01001136 subscr = gprs_subscr_get_or_create(imsi);
Alexander Couzens3326ba72020-12-09 22:02:55 +01001137 if (!subscr) {
1138 vty_out(vty, "Can not create subscriber. Out of memory.%s", imsi);
1139 return CMD_WARNING;
1140 }
Jacob Erlbeckd9193432015-01-19 14:11:46 +01001141 subscr->keep_in_ram = 1;
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001142 gprs_subscr_put(subscr);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001143
1144 return CMD_SUCCESS;
1145}
1146
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001147DEFUN(update_subscr_destroy, update_subscr_destroy_cmd,
1148 UPDATE_SUBSCR_STR "destroy",
1149 UPDATE_SUBSCR_HELP
1150 "Destroy a subscriber entry\n")
1151{
1152 const char *imsi = argv[0];
1153
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001154 struct gprs_subscr *subscr;
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001155
1156 subscr = gprs_subscr_get_by_imsi(imsi);
1157 if (!subscr) {
1158 vty_out(vty, "%% subscriber record does not exist for %s%s",
1159 imsi, VTY_NEWLINE);
1160 return CMD_WARNING;
1161 }
1162
1163 subscr->keep_in_ram = 0;
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +01001164 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001165 gprs_subscr_cancel(subscr);
1166 if (subscr->use_count > 1)
1167 vty_out(vty, "%% subscriber is still in use%s",
1168 VTY_NEWLINE);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001169 gprs_subscr_put(subscr);
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001170
1171 return CMD_SUCCESS;
1172}
1173
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001174#define UL_ERR_STR "system-failure|data-missing|unexpected-data-value|" \
1175 "unknown-subscriber|roaming-not-allowed"
1176
1177#define UL_ERR_HELP \
1178 "Force error code SystemFailure\n" \
1179 "Force error code DataMissing\n" \
1180 "Force error code UnexpectedDataValue\n" \
1181 "Force error code UnknownSubscriber\n" \
1182 "Force error code RoamingNotAllowed\n"
1183
1184DEFUN(update_subscr_update_location_result, update_subscr_update_location_result_cmd,
1185 UPDATE_SUBSCR_STR "update-location-result (ok|" UL_ERR_STR ")",
1186 UPDATE_SUBSCR_HELP
1187 "Complete the update location procedure\n"
1188 "The update location request succeeded\n"
1189 UL_ERR_HELP)
1190{
1191 const char *imsi = argv[0];
1192 const char *ret_code_str = argv[1];
1193
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001194 struct gprs_subscr *subscr;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001195
Jacob Erlbeckd6267d12015-01-19 11:10:04 +01001196 const struct value_string cause_mapping[] = {
1197 { GMM_CAUSE_NET_FAIL, "system-failure" },
1198 { GMM_CAUSE_INV_MAND_INFO, "data-missing" },
1199 { GMM_CAUSE_PROTO_ERR_UNSPEC, "unexpected-data-value" },
1200 { GMM_CAUSE_IMSI_UNKNOWN, "unknown-subscriber" },
1201 { GMM_CAUSE_GPRS_NOTALLOWED, "roaming-not-allowed" },
1202 { 0, NULL }
1203 };
1204
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001205 subscr = gprs_subscr_get_by_imsi(imsi);
1206 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +01001207 vty_out(vty, "%% unable to get subscriber record for %s%s",
1208 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001209 return CMD_WARNING;
1210 }
Jacob Erlbeckd6267d12015-01-19 11:10:04 +01001211
1212 if (strcmp(ret_code_str, "ok") == 0) {
1213 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001214 subscr->authorized = 1;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +01001215 } else {
1216 subscr->sgsn_data->error_cause =
1217 get_string_value(cause_mapping, ret_code_str);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001218 subscr->authorized = 0;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +01001219 }
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001220
1221 gprs_subscr_update(subscr);
1222
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001223 gprs_subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001224
1225 return CMD_SUCCESS;
1226}
1227
1228DEFUN(update_subscr_update_auth_info, update_subscr_update_auth_info_cmd,
1229 UPDATE_SUBSCR_STR "update-auth-info",
1230 UPDATE_SUBSCR_HELP
1231 "Complete the send authentication info procedure\n")
1232{
1233 const char *imsi = argv[0];
1234
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001235 struct gprs_subscr *subscr;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001236
1237 subscr = gprs_subscr_get_by_imsi(imsi);
1238 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +01001239 vty_out(vty, "%% unable to get subscriber record for %s%s",
1240 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001241 return CMD_WARNING;
1242 }
1243
1244 gprs_subscr_update_auth_info(subscr);
1245
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001246 gprs_subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001247
1248 return CMD_SUCCESS;
1249}
1250
Oliver Smithab39b622021-07-05 15:41:05 +02001251DEFUN(page_subscr, page_subscr_info_cmd,
1252 "page imsi IMSI",
1253 "Send a PS paging request to subscriber\n"
1254 "Use the IMSI to select the subscriber\n"
1255 "The IMSI\n")
1256{
1257 const char *imsi = argv[0];
1258 struct sgsn_mm_ctx *mm;
1259
1260 mm = sgsn_mm_ctx_by_imsi(imsi);
1261 if (!mm) {
1262 vty_out(vty, "No MM context for IMSI %s%s", imsi, VTY_NEWLINE);
1263 return CMD_WARNING;
1264 }
1265
1266 gprs_gb_page_ps_ra(mm);
1267 return CMD_SUCCESS;
1268}
1269
Stefan Sperling88220092018-12-11 14:42:00 +01001270DEFUN(cfg_gsup_ipa_name,
1271 cfg_gsup_ipa_name_cmd,
1272 "gsup ipa-name NAME",
1273 "GSUP Parameters\n"
1274 "Set the IPA name of this SGSN\n"
1275 "A unique name for this SGSN. For example: PLMN + redundancy server number: SGSN-901-70-0. "
1276 "This name is used for GSUP routing and must be set if more than one SGSN is connected to the network. "
1277 "The default is 'SGSN-00-00-00-00-00-00'.\n")
1278{
1279 if (vty->type != VTY_FILE) {
1280 vty_out(vty, "The IPA name cannot be changed at run-time; "
1281 "It can only be set in the configuraton file.%s", VTY_NEWLINE);
1282 return CMD_WARNING;
1283 }
1284
1285 g_cfg->sgsn_ipa_name = talloc_strdup(tall_vty_ctx, argv[0]);
1286 return CMD_SUCCESS;
1287}
1288
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001289DEFUN(cfg_gsup_remote_ip, cfg_gsup_remote_ip_cmd,
1290 "gsup remote-ip A.B.C.D",
1291 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001292 "Set the IP address of the remote GSUP server (e.g. OsmoHLR)."
1293 " This setting only applies if 'auth-policy remote' is used.\n"
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001294 "IPv4 Address\n")
1295{
1296 inet_aton(argv[0], &g_cfg->gsup_server_addr.sin_addr);
1297
1298 return CMD_SUCCESS;
1299}
1300
1301DEFUN(cfg_gsup_remote_port, cfg_gsup_remote_port_cmd,
1302 "gsup remote-port <0-65535>",
1303 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001304 "Set the TCP port of the remote GSUP server, see also 'gsup remote-ip'\n"
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001305 "Remote TCP port\n")
1306{
1307 g_cfg->gsup_server_port = atoi(argv[0]);
1308
1309 return CMD_SUCCESS;
1310}
1311
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001312DEFUN(cfg_gsup_oap_id, cfg_gsup_oap_id_cmd,
1313 "gsup oap-id <0-65535>",
1314 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001315 "Set the OAP client ID for authentication on the GSUP protocol."
1316 " This setting only applies if 'auth-policy remote' is used.\n"
1317 "OAP client ID (0 == disabled)\n")
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001318{
1319 /* VTY ensures range */
1320 g_cfg->oap.client_id = (uint16_t)atoi(argv[0]);
1321 return CMD_SUCCESS;
1322}
1323
1324DEFUN(cfg_gsup_oap_k, cfg_gsup_oap_k_cmd,
1325 "gsup oap-k K",
1326 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001327 "Set the OAP shared secret key K for authentication on the GSUP protocol."
1328 " This setting only applies if auth-policy remote is used.\n"
1329 "K value (16 byte) hex\n")
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001330{
1331 const char *k = argv[0];
1332
1333 g_cfg->oap.secret_k_present = 0;
1334
1335 if ((!k) || (strlen(k) == 0))
1336 goto disable;
1337
1338 int k_len = osmo_hexparse(k,
1339 g_cfg->oap.secret_k,
1340 sizeof(g_cfg->oap.secret_k));
1341 if (k_len != 16) {
1342 vty_out(vty, "%% need exactly 16 octets for oap-k, got %d.%s",
1343 k_len, VTY_NEWLINE);
1344 goto disable;
1345 }
1346
1347 g_cfg->oap.secret_k_present = 1;
1348 return CMD_SUCCESS;
1349
1350disable:
1351 if (g_cfg->oap.client_id > 0) {
1352 vty_out(vty, "%% OAP client ID set, but invalid oap-k value disables OAP.%s",
1353 VTY_NEWLINE);
1354 return CMD_WARNING;
1355 }
1356 return CMD_SUCCESS;
1357}
1358
1359DEFUN(cfg_gsup_oap_opc, cfg_gsup_oap_opc_cmd,
1360 "gsup oap-opc OPC",
1361 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001362 "Set the OAP shared secret OPC for authentication on the GSUP protocol."
1363 " This setting only applies if auth-policy remote is used.\n"
1364 "OPC value (16 byte) hex\n")
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001365{
1366 const char *opc = argv[0];
1367
1368 g_cfg->oap.secret_opc_present = 0;
1369
1370 if ((!opc) || (strlen(opc) == 0))
1371 goto disable;
1372
1373 int opc_len = osmo_hexparse(opc,
1374 g_cfg->oap.secret_opc,
1375 sizeof(g_cfg->oap.secret_opc));
1376 if (opc_len != 16) {
1377 vty_out(vty, "%% need exactly 16 octets for oap-opc, got %d.%s",
1378 opc_len, VTY_NEWLINE);
1379 goto disable;
1380 }
1381
1382 g_cfg->oap.secret_opc_present = 1;
1383 return CMD_SUCCESS;
1384
1385disable:
1386 if (g_cfg->oap.client_id > 0) {
1387 vty_out(vty, "%% OAP client ID set, but invalid oap-opc value disables OAP.%s",
1388 VTY_NEWLINE);
1389 return CMD_WARNING;
1390 }
1391 return CMD_SUCCESS;
1392}
1393
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001394DEFUN(cfg_apn_name, cfg_apn_name_cmd,
1395 "access-point-name NAME",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001396 "Globally allow the given APN name for all subscribers.\n"
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001397 "Add this NAME to the list\n")
1398{
1399 return add_apn_ggsn_mapping(vty, argv[0], "", 0);
1400}
1401
1402DEFUN(cfg_no_apn_name, cfg_no_apn_name_cmd,
1403 "no access-point-name NAME",
1404 NO_STR "Configure a global list of allowed APNs\n"
1405 "Remove entry with NAME\n")
1406{
1407 struct apn_ctx *apn_ctx = sgsn_apn_ctx_by_name(argv[0], "");
1408 if (!apn_ctx)
1409 return CMD_SUCCESS;
1410
1411 sgsn_apn_ctx_free(apn_ctx);
1412 return CMD_SUCCESS;
1413}
1414
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001415DEFUN(cfg_cdr_filename, cfg_cdr_filename_cmd,
1416 "cdr filename NAME",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001417 "CDR\n"
1418 "Set the file name for the call-data-record file, logging the data usage of each subscriber.\n"
1419 "filename\n")
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001420{
1421 talloc_free(g_cfg->cdr.filename);
1422 g_cfg->cdr.filename = talloc_strdup(tall_vty_ctx, argv[0]);
1423 return CMD_SUCCESS;
1424}
1425
1426DEFUN(cfg_no_cdr_filename, cfg_no_cdr_filename_cmd,
1427 "no cdr filename",
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +01001428 NO_STR "CDR\nDisable saving CDR to file\n")
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001429{
1430 talloc_free(g_cfg->cdr.filename);
1431 g_cfg->cdr.filename = NULL;
1432 return CMD_SUCCESS;
1433}
1434
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +01001435DEFUN(cfg_cdr_trap, cfg_cdr_trap_cmd,
1436 "cdr trap",
1437 "CDR\nEnable sending CDR via TRAP CTRL messages\n")
1438{
1439 g_cfg->cdr.trap = true;
1440 return CMD_SUCCESS;
1441}
1442
1443DEFUN(cfg_no_cdr_trap, cfg_no_cdr_trap_cmd,
1444 "no cdr trap",
1445 NO_STR "CDR\nDisable sending CDR via TRAP CTRL messages\n")
1446{
1447 g_cfg->cdr.trap = false;
1448 return CMD_SUCCESS;
1449}
1450
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001451DEFUN(cfg_cdr_interval, cfg_cdr_interval_cmd,
1452 "cdr interval <1-2147483647>",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001453 "CDR\n"
1454 "Set the interval for the call-data-record file\n"
1455 "interval in seconds\n")
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001456{
1457 g_cfg->cdr.interval = atoi(argv[0]);
1458 return CMD_SUCCESS;
1459}
1460
Philippf1f34362016-08-26 17:00:21 +02001461#define COMPRESSION_STR "Configure compression\n"
1462DEFUN(cfg_no_comp_rfc1144, cfg_no_comp_rfc1144_cmd,
1463 "no compression rfc1144",
1464 NO_STR COMPRESSION_STR "disable rfc1144 TCP/IP header compression\n")
1465{
1466 g_cfg->pcomp_rfc1144.active = 0;
1467 g_cfg->pcomp_rfc1144.passive = 0;
1468 return CMD_SUCCESS;
1469}
1470
1471DEFUN(cfg_comp_rfc1144, cfg_comp_rfc1144_cmd,
1472 "compression rfc1144 active slots <1-256>",
1473 COMPRESSION_STR
Ruben Undheim55fcf112018-09-25 22:59:34 +02001474 "RFC1144 Header compression scheme\n"
Philippf1f34362016-08-26 17:00:21 +02001475 "Compression is actively proposed\n"
1476 "Number of compression state slots\n"
1477 "Number of compression state slots\n")
1478{
1479 g_cfg->pcomp_rfc1144.active = 1;
1480 g_cfg->pcomp_rfc1144.passive = 1;
1481 g_cfg->pcomp_rfc1144.s01 = atoi(argv[0]) - 1;
1482 return CMD_SUCCESS;
1483}
1484
1485DEFUN(cfg_comp_rfc1144p, cfg_comp_rfc1144p_cmd,
1486 "compression rfc1144 passive",
1487 COMPRESSION_STR
Ruben Undheim55fcf112018-09-25 22:59:34 +02001488 "RFC1144 Header compression scheme\n"
Philippf1f34362016-08-26 17:00:21 +02001489 "Compression is available on request\n")
1490{
1491 g_cfg->pcomp_rfc1144.active = 0;
1492 g_cfg->pcomp_rfc1144.passive = 1;
1493 return CMD_SUCCESS;
1494}
1495
Philipp73f83d52016-09-02 13:38:01 +02001496DEFUN(cfg_no_comp_v42bis, cfg_no_comp_v42bis_cmd,
1497 "no compression v42bis",
1498 NO_STR COMPRESSION_STR "disable V.42bis data compression\n")
1499{
1500 g_cfg->dcomp_v42bis.active = 0;
1501 g_cfg->dcomp_v42bis.passive = 0;
1502 return CMD_SUCCESS;
1503}
1504
1505DEFUN(cfg_comp_v42bis, cfg_comp_v42bis_cmd,
1506 "compression v42bis active direction (ms|sgsn|both) codewords <512-65535> strlen <6-250>",
1507 COMPRESSION_STR
Ruben Undheim55fcf112018-09-25 22:59:34 +02001508 "V.42bis data compression scheme\n"
Philipp73f83d52016-09-02 13:38:01 +02001509 "Compression is actively proposed\n"
1510 "Direction in which the compression shall be active (p0)\n"
1511 "Compress ms->sgsn direction only\n"
1512 "Compress sgsn->ms direction only\n"
1513 "Both directions\n"
1514 "Number of codewords (p1)\n"
1515 "Number of codewords\n"
1516 "Maximum string length (p2)\n" "Maximum string length\n")
1517{
1518 g_cfg->dcomp_v42bis.active = 1;
1519 g_cfg->dcomp_v42bis.passive = 1;
1520
1521 switch (argv[0][0]) {
1522 case 'm':
1523 g_cfg->dcomp_v42bis.p0 = 1;
1524 break;
1525 case 's':
1526 g_cfg->dcomp_v42bis.p0 = 2;
1527 break;
1528 case 'b':
1529 g_cfg->dcomp_v42bis.p0 = 3;
1530 break;
1531 }
1532
1533 g_cfg->dcomp_v42bis.p1 = atoi(argv[1]);
1534 g_cfg->dcomp_v42bis.p2 = atoi(argv[2]);
1535 return CMD_SUCCESS;
1536}
1537
1538DEFUN(cfg_comp_v42bisp, cfg_comp_v42bisp_cmd,
1539 "compression v42bis passive",
1540 COMPRESSION_STR
Ruben Undheim55fcf112018-09-25 22:59:34 +02001541 "V.42bis data compression scheme\n"
Philipp73f83d52016-09-02 13:38:01 +02001542 "Compression is available on request\n")
1543{
1544 g_cfg->dcomp_v42bis.active = 0;
1545 g_cfg->dcomp_v42bis.passive = 1;
1546 return CMD_SUCCESS;
1547}
1548
Pau Espin Pedrol2c908992019-08-19 19:06:06 +02001549#if BUILD_IU
1550DEFUN(cfg_sgsn_cs7_instance_iu,
1551 cfg_sgsn_cs7_instance_iu_cmd,
1552 "cs7-instance-iu <0-15>",
1553 "Set SS7 to be used by the Iu-Interface.\n" "SS7 instance reference number (default: 0)\n")
1554{
1555 g_cfg->iu.cs7_instance = atoi(argv[0]);
1556 return CMD_SUCCESS;
1557}
1558#endif
1559
Pau Espin Pedrole5c89982021-05-03 18:16:42 +02001560DEFUN(cfg_sgsn_mme, cfg_sgsn_mme_cmd,
1561 "mme NAME",
1562 "Configure an MME peer\n"
1563 "Name identifying the MME peer\n")
1564{
1565 struct sgsn_mme_ctx *mme;
1566
1567 mme = sgsn_mme_ctx_find_alloc(sgsn, argv[0]);
1568 if (!mme)
1569 return CMD_WARNING;
1570
1571 vty->node = MME_NODE;
1572 vty->index = mme;
1573
1574 return CMD_SUCCESS;
1575}
1576
1577DEFUN(cfg_sgsn_no_mme, cfg_sgsn_no_mme_cmd,
1578 "no mme NAME",
1579 NO_STR "Delete an MME peer configuration\n"
1580 "Name identifying the MME peer\n")
1581{
1582 struct sgsn_mme_ctx *mme;
1583
1584 mme = sgsn_mme_ctx_by_name(sgsn, argv[0]);
1585 if (!mme) {
1586 vty_out(vty, "%% MME %s doesn't exist.%s",
1587 argv[0], VTY_NEWLINE);
1588 return CMD_WARNING;
1589 }
1590
1591 sgsn_mme_ctx_free(mme);
1592
1593 return CMD_SUCCESS;
1594}
1595
1596#define GTP_STR "Configure GTP connection\n"
1597
1598DEFUN(cfg_mme_remote_ip, cfg_mme_remote_ip_cmd,
1599 "gtp remote-ip A.B.C.D",
1600 GTP_STR "Set Remote GTP IP address\n" IP_STR)
1601{
1602 struct sgsn_mme_ctx *mme = (struct sgsn_mme_ctx *) vty->index;
1603
1604 inet_aton(argv[0], &mme->remote_addr);
1605
1606 return CMD_SUCCESS;
1607}
1608
1609#define RAN_INFO_STR "Configure RAN Information Relay routing\n"
1610#define TAI_DOC "MCC\n" "MNC\n" "TAC\n"
1611
1612DEFUN(cfg_mme_ran_info_relay_tai, cfg_mme_ran_info_relay_tai_cmd,
1613 "gtp ran-info-relay <0-999> <0-999> <0-65535>",
1614 GTP_STR RAN_INFO_STR TAI_DOC)
1615{
1616 struct sgsn_mme_ctx *mme = (struct sgsn_mme_ctx *) vty->index;
1617 struct sgsn_mme_ctx *mme_tmp;
1618 struct osmo_eutran_tai tai;
1619
1620 const char *mcc = argv[0];
1621 const char *mnc = argv[1];
1622 const char *tac = argv[2];
1623
1624 if (osmo_mcc_from_str(mcc, &tai.mcc)) {
1625 vty_out(vty, "%% Error decoding MCC: %s%s", mcc, VTY_NEWLINE);
1626 return CMD_WARNING;
1627 }
1628 if (osmo_mnc_from_str(mnc, &tai.mnc, &tai.mnc_3_digits)) {
1629 vty_out(vty, "%% Error decoding MNC: %s%s", mnc, VTY_NEWLINE);
1630 return CMD_WARNING;
1631 }
1632 tai.tac = atoi(tac);
1633
1634 if ((mme_tmp = sgsn_mme_ctx_by_route(sgsn, &tai))) {
1635 if (mme_tmp != mme) {
1636 vty_out(vty, "%% Another MME %s already contains this route%s",
1637 mme_tmp->name, VTY_NEWLINE);
1638 return CMD_WARNING;
1639 }
1640 /* else: NO-OP, return */
1641 return CMD_SUCCESS;
1642 }
1643
1644 sgsn_mme_ctx_route_add(mme, &tai);
1645 return CMD_SUCCESS;
1646}
1647
1648DEFUN(cfg_mme_no_ran_info_relay_tai, cfg_mme_no_ran_info_relay_tai_cmd,
1649 "no gtp ran-info-relay <0-999> <0-999> <0-65535>",
1650 NO_STR GTP_STR RAN_INFO_STR TAI_DOC)
1651{
1652 struct sgsn_mme_ctx *mme = (struct sgsn_mme_ctx *) vty->index;
1653 struct sgsn_mme_ctx *mme_tmp;
1654 struct osmo_eutran_tai tai;
1655
1656 const char *mcc = argv[0];
1657 const char *mnc = argv[1];
1658 const char *tac = argv[2];
1659
1660 if (osmo_mcc_from_str(mcc, &tai.mcc)) {
1661 vty_out(vty, "%% Error decoding MCC: %s%s", mcc, VTY_NEWLINE);
1662 return CMD_WARNING;
1663 }
1664 if (osmo_mnc_from_str(mnc, &tai.mnc, &tai.mnc_3_digits)) {
1665 vty_out(vty, "%% Error decoding MNC: %s%s", mnc, VTY_NEWLINE);
1666 return CMD_WARNING;
1667 }
1668 tai.tac = atoi(tac);
1669
1670 if ((mme_tmp = sgsn_mme_ctx_by_route(sgsn, &tai))) {
1671 if (mme_tmp != mme) {
1672 vty_out(vty, "%% Another MME %s contains this route%s",
1673 mme_tmp->name, VTY_NEWLINE);
1674 return CMD_WARNING;
1675 }
1676 sgsn_mme_ctx_route_del(mme, &tai);
1677 return CMD_SUCCESS;
1678 } else {
1679 vty_out(vty, "%% This route doesn't exist in current MME %s%s",
1680 mme->name, VTY_NEWLINE);
1681 return CMD_WARNING;
1682 }
1683}
1684
1685DEFUN(cfg_mme_ran_info_relay_default, cfg_mme_ran_info_relay_default_cmd,
1686 "gtp ran-info-relay default",
1687 GTP_STR RAN_INFO_STR "Set as default route")
1688{
1689 struct sgsn_mme_ctx *mme = (struct sgsn_mme_ctx *) vty->index;
1690 struct sgsn_mme_ctx *default_mme;
1691
1692 if (mme->default_route)
1693 return CMD_SUCCESS; /* NO-OP */
1694
1695 if ((default_mme = sgsn_mme_ctx_by_default_route(sgsn))) {
1696 vty_out(vty, "%% Another MME %s is already set as default route, "
1697 "remove it before setting it here.%s",
1698 default_mme->name, VTY_NEWLINE);
1699 return CMD_WARNING;
1700 }
1701
1702 mme->default_route = true;
1703 return CMD_SUCCESS;
1704}
1705
1706DEFUN(cfg_mme_no_ran_info_relay_default, cfg_mme_no_ran_info_relay_default_cmd,
1707 "no gtp ran-info-relay default",
1708 NO_STR GTP_STR RAN_INFO_STR "Set as default route")
1709{
1710 struct sgsn_mme_ctx *mme = (struct sgsn_mme_ctx *) vty->index;
1711 mme->default_route = false;
1712 return CMD_SUCCESS;
1713}
1714
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001715int sgsn_vty_init(struct sgsn_config *cfg)
Harald Welte288be162010-05-01 16:48:27 +02001716{
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001717 g_cfg = cfg;
1718
Pau Espin Pedrola299d652019-08-14 19:11:10 +02001719 g_cfg->T_defs = sgsn_T_defs;
1720 osmo_tdefs_reset(g_cfg->T_defs);
1721
Harald Welted193cb32010-05-17 22:58:03 +02001722 install_element_ve(&show_sgsn_cmd);
1723 //install_element_ve(&show_mmctx_tlli_cmd);
1724 install_element_ve(&show_mmctx_imsi_cmd);
1725 install_element_ve(&show_mmctx_all_cmd);
1726 install_element_ve(&show_pdpctx_all_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001727 install_element_ve(&show_subscr_cache_cmd);
Pau Espin Pedrola299d652019-08-14 19:11:10 +02001728 install_element_ve(&show_timer_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001729
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01001730 install_element(ENABLE_NODE, &update_subscr_insert_auth_triplet_cmd);
Jacob Erlbeckd9193432015-01-19 14:11:46 +01001731 install_element(ENABLE_NODE, &update_subscr_create_cmd);
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001732 install_element(ENABLE_NODE, &update_subscr_destroy_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001733 install_element(ENABLE_NODE, &update_subscr_cancel_cmd);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001734 install_element(ENABLE_NODE, &update_subscr_update_location_result_cmd);
1735 install_element(ENABLE_NODE, &update_subscr_update_auth_info_cmd);
Oliver Smithab39b622021-07-05 15:41:05 +02001736 install_element(ENABLE_NODE, &page_subscr_info_cmd);
Alexander Couzensc503f0a2018-08-07 17:50:04 +02001737 install_element(ENABLE_NODE, &reset_sgsn_state_cmd);
Harald Welte288be162010-05-01 16:48:27 +02001738
1739 install_element(CONFIG_NODE, &cfg_sgsn_cmd);
1740 install_node(&sgsn_node, config_write_sgsn);
Keithc70e8382020-10-19 22:24:48 +02001741 install_element(SGSN_NODE, &cfg_sgsn_state_dir_cmd);
Harald Weltee300d002010-06-02 12:41:34 +02001742 install_element(SGSN_NODE, &cfg_sgsn_bind_addr_cmd);
Harald Welted193cb32010-05-17 22:58:03 +02001743 install_element(SGSN_NODE, &cfg_ggsn_remote_ip_cmd);
1744 //install_element(SGSN_NODE, &cfg_ggsn_remote_port_cmd);
1745 install_element(SGSN_NODE, &cfg_ggsn_gtp_version_cmd);
Pau Espin Pedrolfa120102018-07-09 20:37:47 +02001746 install_element(SGSN_NODE, &cfg_ggsn_echo_interval_cmd);
Pau Espin Pedrola83850c2018-07-10 12:43:59 +02001747 install_element(SGSN_NODE, &cfg_ggsn_no_echo_interval_cmd);
Harald Welte7f6da482013-03-19 11:00:13 +01001748 install_element(SGSN_NODE, &cfg_imsi_acl_cmd);
Harald Welte3dfb5492013-03-19 11:48:54 +01001749 install_element(SGSN_NODE, &cfg_auth_policy_cmd);
Vadim Yanitskiy794f4462019-05-27 05:39:06 +07001750 install_element(SGSN_NODE, &cfg_authentication_cmd);
Eric2f898262021-05-19 18:57:50 +02001751
1752 /* order matters here: ensure we attempt to parse our new command first! */
1753 install_element(SGSN_NODE, &cfg_encrypt2_cmd);
Max93408ae2016-06-28 14:10:16 +02001754 install_element(SGSN_NODE, &cfg_encrypt_cmd);
Neels Hofmeyr3c7656a2022-03-07 15:38:59 +01001755 install_element(SGSN_NODE, &cfg_encryption_uea_cmd);
Eric2f898262021-05-19 18:57:50 +02001756
Stefan Sperling88220092018-12-11 14:42:00 +01001757 install_element(SGSN_NODE, &cfg_gsup_ipa_name_cmd);
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001758 install_element(SGSN_NODE, &cfg_gsup_remote_ip_cmd);
1759 install_element(SGSN_NODE, &cfg_gsup_remote_port_cmd);
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001760 install_element(SGSN_NODE, &cfg_gsup_oap_id_cmd);
1761 install_element(SGSN_NODE, &cfg_gsup_oap_k_cmd);
1762 install_element(SGSN_NODE, &cfg_gsup_oap_opc_cmd);
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +01001763 install_element(SGSN_NODE, &cfg_apn_ggsn_cmd);
1764 install_element(SGSN_NODE, &cfg_apn_imsi_ggsn_cmd);
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001765 install_element(SGSN_NODE, &cfg_apn_name_cmd);
1766 install_element(SGSN_NODE, &cfg_no_apn_name_cmd);
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001767 install_element(SGSN_NODE, &cfg_cdr_filename_cmd);
1768 install_element(SGSN_NODE, &cfg_no_cdr_filename_cmd);
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +01001769 install_element(SGSN_NODE, &cfg_cdr_trap_cmd);
1770 install_element(SGSN_NODE, &cfg_no_cdr_trap_cmd);
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001771 install_element(SGSN_NODE, &cfg_cdr_interval_cmd);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001772 install_element(SGSN_NODE, &cfg_ggsn_dynamic_lookup_cmd);
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +08001773 install_element(SGSN_NODE, &cfg_grx_ggsn_cmd);
Harald Welte288be162010-05-01 16:48:27 +02001774
Pau Espin Pedrola299d652019-08-14 19:11:10 +02001775 install_element(SGSN_NODE, &cfg_sgsn_timer_cmd);
Harald Welte94508822015-08-15 19:08:21 +02001776
Philippf1f34362016-08-26 17:00:21 +02001777 install_element(SGSN_NODE, &cfg_no_comp_rfc1144_cmd);
1778 install_element(SGSN_NODE, &cfg_comp_rfc1144_cmd);
1779 install_element(SGSN_NODE, &cfg_comp_rfc1144p_cmd);
Philipp73f83d52016-09-02 13:38:01 +02001780 install_element(SGSN_NODE, &cfg_no_comp_v42bis_cmd);
1781 install_element(SGSN_NODE, &cfg_comp_v42bis_cmd);
1782 install_element(SGSN_NODE, &cfg_comp_v42bisp_cmd);
Neels Hofmeyr2188a772016-05-20 21:59:55 +02001783
Pau Espin Pedrole5c89982021-05-03 18:16:42 +02001784 install_element(SGSN_NODE, &cfg_sgsn_mme_cmd);
1785 install_element(SGSN_NODE, &cfg_sgsn_no_mme_cmd);
1786 install_node(&mme_node, NULL);
1787 install_element(MME_NODE, &cfg_mme_remote_ip_cmd);
1788 install_element(MME_NODE, &cfg_mme_ran_info_relay_default_cmd);
1789 install_element(MME_NODE, &cfg_mme_no_ran_info_relay_default_cmd);
1790 install_element(MME_NODE, &cfg_mme_ran_info_relay_tai_cmd);
1791 install_element(MME_NODE, &cfg_mme_no_ran_info_relay_tai_cmd);
1792
Neels Hofmeyr2188a772016-05-20 21:59:55 +02001793#ifdef BUILD_IU
Pau Espin Pedrol2c908992019-08-19 19:06:06 +02001794 install_element(SGSN_NODE, &cfg_sgsn_cs7_instance_iu_cmd);
Neels Hofmeyra7a39472017-07-05 15:19:52 +02001795 ranap_iu_vty_init(SGSN_NODE, &g_cfg->iu.rab_assign_addr_enc);
Neels Hofmeyr2188a772016-05-20 21:59:55 +02001796#endif
Harald Welte288be162010-05-01 16:48:27 +02001797 return 0;
1798}
1799
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001800int sgsn_parse_config(const char *config_file)
Harald Welte288be162010-05-01 16:48:27 +02001801{
1802 int rc;
1803
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001804 /* make sure sgsn_vty_init() was called before this */
1805 OSMO_ASSERT(g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +01001806
Neels Hofmeyr340a7e92022-03-07 15:37:24 +01001807 g_cfg->gea_encryption_mask = 0x1; /* support GEA0 by default unless specific encryption config exists */
Neels Hofmeyr3c7656a2022-03-07 15:38:59 +01001808 g_cfg->uea_encryption_mask = (1 << OSMO_UTRAN_UEA0); /* support UEA0 by default unless specific encryption config exists */
Eric2f898262021-05-19 18:57:50 +02001809
Harald Weltedcccb182010-05-16 20:52:23 +02001810 rc = vty_read_config_file(config_file, NULL);
Harald Welte288be162010-05-01 16:48:27 +02001811 if (rc < 0) {
1812 fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
1813 return rc;
1814 }
1815
Neels Hofmeyr27355c92017-02-24 06:28:31 +01001816 if (g_cfg->auth_policy == SGSN_AUTH_POLICY_REMOTE
1817 && !(g_cfg->gsup_server_addr.sin_addr.s_addr
1818 && g_cfg->gsup_server_port)) {
1819 fprintf(stderr, "Configuration error:"
1820 " 'auth-policy remote' requires both"
1821 " 'gsup remote-ip' and 'gsup remote-port'\n");
1822 return -EINVAL;
1823 }
1824
Harald Welte288be162010-05-01 16:48:27 +02001825 return 0;
1826}