blob: d7584bcb4066cef06cd20b457eb5c8ac2064f1de [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>
40#include <osmocom/sgsn/vty.h>
Harald Weltef4b2c4c2018-09-16 07:53:41 +020041#include <osmocom/gsupclient/gsup_client.h>
Harald Welte288be162010-05-01 16:48:27 +020042
Pau Espin Pedrola299d652019-08-14 19:11:10 +020043#include <osmocom/vty/tdef_vty.h>
Harald Welte4b037e42010-05-19 19:45:32 +020044#include <osmocom/vty/command.h>
45#include <osmocom/vty/vty.h>
Pablo Neira Ayuso6110a3f2011-03-28 19:35:00 +020046#include <osmocom/vty/misc.h>
Max93408ae2016-06-28 14:10:16 +020047#include <osmocom/crypt/gprs_cipher.h>
Jacob Erlbeck80547992014-12-19 19:19:46 +010048#include <osmocom/abis/ipa.h>
49
Alexander Couzensc503f0a2018-08-07 17:50:04 +020050#include <osmocom/gprs/gprs_bssgp.h>
51
Harald Welted193cb32010-05-17 22:58:03 +020052#include <pdp.h>
Maxbaabc682017-10-20 13:39:57 +020053#include <gtp.h>
Harald Welted193cb32010-05-17 22:58:03 +020054
Neels Hofmeyr2188a772016-05-20 21:59:55 +020055#include "../../bscconfig.h"
56
57#ifdef BUILD_IU
Neels Hofmeyra7a39472017-07-05 15:19:52 +020058#include <osmocom/ranap/iu_client.h>
Neels Hofmeyr2188a772016-05-20 21:59:55 +020059#endif
60
Pau Espin Pedrolb1d1c242018-10-30 17:27:59 +010061extern void *tall_sgsn_ctx;
Neels Hofmeyree6cfdc2017-07-13 02:03:50 +020062
Harald Welte288be162010-05-01 16:48:27 +020063static struct sgsn_config *g_cfg = NULL;
64
Jacob Erlbeck106f5472014-11-04 10:08:37 +010065const struct value_string sgsn_auth_pol_strs[] = {
66 { SGSN_AUTH_POLICY_OPEN, "accept-all" },
67 { SGSN_AUTH_POLICY_CLOSED, "closed" },
68 { SGSN_AUTH_POLICY_ACL_ONLY, "acl-only" },
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +010069 { SGSN_AUTH_POLICY_REMOTE, "remote" },
Jacob Erlbeck106f5472014-11-04 10:08:37 +010070 { 0, NULL }
71};
72
Harald Welte94508822015-08-15 19:08:21 +020073/* Section 11.2.2 / Table 11.3a GPRS Mobility management timers – MS side */
74#define GSM0408_T3312_SECS (10*60) /* periodic RAU interval, default 54min */
75
76/* Section 11.2.2 / Table 11.4 MM timers netwokr side */
77#define GSM0408_T3322_SECS 6 /* DETACH_REQ -> DETACH_ACC */
78#define GSM0408_T3350_SECS 6 /* waiting for ATT/RAU/TMSI COMPL */
79#define GSM0408_T3360_SECS 6 /* waiting for AUTH/CIPH RESP */
80#define GSM0408_T3370_SECS 6 /* waiting for ID RESP */
81
Alexander Couzens5ba6fb32017-01-31 18:04:27 +010082/* Section 11.2.2 / Table 11.4a MM timers network side */
Harald Welte94508822015-08-15 19:08:21 +020083#define GSM0408_T3313_SECS 30 /* waiting for paging response */
84#define GSM0408_T3314_SECS 44 /* force to STBY on expiry, Ready timer */
85#define GSM0408_T3316_SECS 44
86
87/* Section 11.3 / Table 11.2d Timers of Session Management - network side */
88#define GSM0408_T3385_SECS 8 /* wait for ACT PDP CTX REQ */
89#define GSM0408_T3386_SECS 8 /* wait for MODIFY PDP CTX ACK */
90#define GSM0408_T3395_SECS 8 /* wait for DEACT PDP CTX ACK */
91#define GSM0408_T3397_SECS 8 /* wait for DEACT AA PDP CTX ACK */
92
Alexander Couzensafadd102019-10-08 14:30:59 +020093/* Non spec timer */
94#define NONSPEC_X1001_SECS 5 /* wait for a RANAP Release Complete */
95
Pau Espin Pedrola299d652019-08-14 19:11:10 +020096
97static struct osmo_tdef sgsn_T_defs[] = {
98 { .T=3312, .default_val=GSM0408_T3312_SECS, .desc="Periodic RA Update timer (s)" },
99 { .T=3313, .default_val=GSM0408_T3313_SECS, .desc="Waiting for paging response timer (s)" },
Alexander Couzens39cbecd2017-02-03 22:16:05 +0100100 { .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 +0200101 { .T=3316, .default_val=GSM0408_T3316_SECS, .desc="AA-Ready timer (s)" },
102 { .T=3322, .default_val=GSM0408_T3322_SECS, .desc="Detach request -> accept timer (s)" },
103 { .T=3350, .default_val=GSM0408_T3350_SECS, .desc="Waiting for ATT/RAU/TMSI_COMPL timer (s)" },
104 { .T=3360, .default_val=GSM0408_T3360_SECS, .desc="Waiting for AUTH/CIPH response timer (s)" },
105 { .T=3370, .default_val=GSM0408_T3370_SECS, .desc="Waiting for IDENTITY response timer (s)" },
106 { .T=3385, .default_val=GSM0408_T3385_SECS, .desc="Wait for ACT PDP CTX REQ timer (s)" },
107 { .T=3386, .default_val=GSM0408_T3386_SECS, .desc="Wait for MODIFY PDP CTX ACK timer (s)" },
108 { .T=3395, .default_val=GSM0408_T3395_SECS, .desc="Wait for DEACT PDP CTX ACK timer (s)" },
109 { .T=3397, .default_val=GSM0408_T3397_SECS, .desc="Wait for DEACT AA PDP CTX ACK timer (s)" },
Alexander Couzens3bad31b2019-09-11 02:17:31 +0200110 /* non spec timers */
Alexander Couzensafadd102019-10-08 14:30:59 +0200111 { .T=-1001, .default_val=NONSPEC_X1001_SECS, .desc="RANAP Release timeout. Wait for RANAP Release Complete."
112 "On expiry release Iu connection (s)" },
Alexander Couzens3bad31b2019-09-11 02:17:31 +0200113 { .T=-3314, .default_val=GSM0408_T3314_SECS, .desc="Iu User inactivity timer. 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
180static int config_write_sgsn(struct vty *vty)
181{
Harald Welte77289c22010-05-18 14:32:29 +0200182 struct sgsn_ggsn_ctx *gctx;
Harald Welte7f6da482013-03-19 11:00:13 +0100183 struct imsi_acl_entry *acl;
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100184 struct apn_ctx *actx;
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800185 struct ares_addr_node *server;
Harald Welte288be162010-05-01 16:48:27 +0200186
187 vty_out(vty, "sgsn%s", VTY_NEWLINE);
188
Keithc70e8382020-10-19 22:24:48 +0200189 vty_out(vty, " gtp state-dir %s%s",
190 g_cfg->gtp_statedir, VTY_NEWLINE);
Harald Weltee300d002010-06-02 12:41:34 +0200191 vty_out(vty, " gtp local-ip %s%s",
192 inet_ntoa(g_cfg->gtp_listenaddr.sin_addr), VTY_NEWLINE);
193
Harald Welted193cb32010-05-17 22:58:03 +0200194 llist_for_each_entry(gctx, &sgsn_ggsn_ctxts, list) {
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800195 if (gctx->id == UINT32_MAX)
196 continue;
197
Harald Welteff3bde82010-05-19 15:09:09 +0200198 vty_out(vty, " ggsn %u remote-ip %s%s", gctx->id,
Harald Welted193cb32010-05-17 22:58:03 +0200199 inet_ntoa(gctx->remote_addr), VTY_NEWLINE);
Harald Welteff3bde82010-05-19 15:09:09 +0200200 vty_out(vty, " ggsn %u gtp-version %u%s", gctx->id,
Harald Welted193cb32010-05-17 22:58:03 +0200201 gctx->gtp_version, VTY_NEWLINE);
Pau Espin Pedrolaa89f5d2019-08-28 16:08:45 +0200202 if (gctx->echo_interval)
203 vty_out(vty, " ggsn %u echo-interval %u%s",
Pau Espin Pedrolfa120102018-07-09 20:37:47 +0200204 gctx->id, gctx->echo_interval, VTY_NEWLINE);
Pau Espin Pedrola83850c2018-07-10 12:43:59 +0200205 else
206 vty_out(vty, " ggsn %u no echo-interval%s",
207 gctx->id, VTY_NEWLINE);
Harald Welte288be162010-05-01 16:48:27 +0200208 }
209
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800210 if (sgsn->cfg.dynamic_lookup)
211 vty_out(vty, " ggsn dynamic%s", VTY_NEWLINE);
212
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800213 for (server = sgsn->ares_servers; server; server = server->next)
214 vty_out(vty, " grx-dns-add %s%s", inet_ntoa(server->addr.addr4), VTY_NEWLINE);
215
Max93408ae2016-06-28 14:10:16 +0200216 if (g_cfg->cipher != GPRS_ALGO_GEA0)
217 vty_out(vty, " encryption %s%s",
218 get_value_string(gprs_cipher_names, g_cfg->cipher),
219 VTY_NEWLINE);
Stefan Sperling88220092018-12-11 14:42:00 +0100220 if (g_cfg->sgsn_ipa_name)
221 vty_out(vty, " gsup ipa-name %s%s", g_cfg->sgsn_ipa_name, VTY_NEWLINE);
Jacob Erlbeck39f040d2014-12-18 12:46:47 +0100222 if (g_cfg->gsup_server_addr.sin_addr.s_addr)
223 vty_out(vty, " gsup remote-ip %s%s",
224 inet_ntoa(g_cfg->gsup_server_addr.sin_addr), VTY_NEWLINE);
225 if (g_cfg->gsup_server_port)
226 vty_out(vty, " gsup remote-port %d%s",
227 g_cfg->gsup_server_port, VTY_NEWLINE);
Pau Espin Pedrold1463bc2019-06-13 19:03:25 +0200228 if (g_cfg->auth_policy == SGSN_AUTH_POLICY_REMOTE && !g_cfg->require_authentication)
229 vty_out(vty, " authentication optional%s", VTY_NEWLINE);
Max176b62a2016-07-04 11:09:07 +0200230 vty_out(vty, " auth-policy %s%s",
231 get_value_string(sgsn_auth_pol_strs, g_cfg->auth_policy),
232 VTY_NEWLINE);
Neels Hofmeyr568a7272015-10-12 11:57:38 +0200233
234 vty_out(vty, " gsup oap-id %d%s",
235 (int)g_cfg->oap.client_id, VTY_NEWLINE);
236 if (g_cfg->oap.secret_k_present != 0)
237 vty_out(vty, " gsup oap-k %s%s",
238 osmo_hexdump_nospc(g_cfg->oap.secret_k, sizeof(g_cfg->oap.secret_k)),
239 VTY_NEWLINE);
240 if (g_cfg->oap.secret_opc_present != 0)
241 vty_out(vty, " gsup oap-opc %s%s",
242 osmo_hexdump_nospc(g_cfg->oap.secret_opc, sizeof(g_cfg->oap.secret_opc)),
243 VTY_NEWLINE);
244
Harald Welte7f6da482013-03-19 11:00:13 +0100245 llist_for_each_entry(acl, &g_cfg->imsi_acl, list)
246 vty_out(vty, " imsi-acl add %s%s", acl->imsi, VTY_NEWLINE);
247
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100248 if (llist_empty(&sgsn_apn_ctxts))
249 vty_out(vty, " ! apn * ggsn 0%s", VTY_NEWLINE);
250 llist_for_each_entry(actx, &sgsn_apn_ctxts, list) {
251 if (strlen(actx->imsi_prefix) > 0)
Holger Hans Peter Freytherb7ae0b32015-05-29 15:11:55 +0200252 vty_out(vty, " apn %s imsi-prefix %s ggsn %u%s",
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100253 actx->name, actx->imsi_prefix, actx->ggsn->id,
254 VTY_NEWLINE);
255 else
Holger Hans Peter Freytherb7ae0b32015-05-29 15:11:55 +0200256 vty_out(vty, " apn %s ggsn %u%s", actx->name,
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100257 actx->ggsn->id, VTY_NEWLINE);
258 }
259
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +0200260 if (g_cfg->cdr.filename)
261 vty_out(vty, " cdr filename %s%s", g_cfg->cdr.filename, VTY_NEWLINE);
262 else
263 vty_out(vty, " no cdr filename%s", VTY_NEWLINE);
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +0100264 if (g_cfg->cdr.trap)
265 vty_out(vty, " cdr trap%s", VTY_NEWLINE);
266 else
267 vty_out(vty, " no cdr trap%s", VTY_NEWLINE);
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +0200268 vty_out(vty, " cdr interval %d%s", g_cfg->cdr.interval, VTY_NEWLINE);
269
Pau Espin Pedrola299d652019-08-14 19:11:10 +0200270 osmo_tdef_vty_write(vty, g_cfg->T_defs, " timer ");
Harald Welte94508822015-08-15 19:08:21 +0200271
Philippf1f34362016-08-26 17:00:21 +0200272 if (g_cfg->pcomp_rfc1144.active) {
273 vty_out(vty, " compression rfc1144 active slots %d%s",
274 g_cfg->pcomp_rfc1144.s01 + 1, VTY_NEWLINE);
275 } else if (g_cfg->pcomp_rfc1144.passive) {
276 vty_out(vty, " compression rfc1144 passive%s", VTY_NEWLINE);
277 } else
278 vty_out(vty, " no compression rfc1144%s", VTY_NEWLINE);
279
Philipp73f83d52016-09-02 13:38:01 +0200280 if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 1) {
281 vty_out(vty,
282 " compression v42bis active direction sgsn codewords %d strlen %d%s",
283 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
284 VTY_NEWLINE);
285 } else if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 2) {
286 vty_out(vty,
287 " compression v42bis active direction ms codewords %d strlen %d%s",
288 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
289 VTY_NEWLINE);
290 } else if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 3) {
291 vty_out(vty,
292 " compression v42bis active direction both codewords %d strlen %d%s",
293 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
294 VTY_NEWLINE);
295 } else if (g_cfg->dcomp_v42bis.passive) {
296 vty_out(vty, " compression v42bis passive%s", VTY_NEWLINE);
297 } else
298 vty_out(vty, " no compression v42bis%s", VTY_NEWLINE);
299
Neels Hofmeyr2188a772016-05-20 21:59:55 +0200300#ifdef BUILD_IU
Pau Espin Pedrol2c908992019-08-19 19:06:06 +0200301 vty_out(vty, " cs7-instance-iu %u%s", g_cfg->iu.cs7_instance,
302 VTY_NEWLINE);
Neels Hofmeyra7a39472017-07-05 15:19:52 +0200303 ranap_iu_vty_config_write(vty, " ");
Neels Hofmeyr2188a772016-05-20 21:59:55 +0200304#endif
305
Harald Welte288be162010-05-01 16:48:27 +0200306 return CMD_SUCCESS;
307}
308
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100309#define SGSN_STR "Configure the SGSN\n"
310#define GGSN_STR "Configure the GGSN information\n"
Harald Weltee300d002010-06-02 12:41:34 +0200311
312DEFUN(cfg_sgsn, cfg_sgsn_cmd,
313 "sgsn",
314 SGSN_STR)
Harald Welte288be162010-05-01 16:48:27 +0200315{
316 vty->node = SGSN_NODE;
317 return CMD_SUCCESS;
318}
319
Keithc70e8382020-10-19 22:24:48 +0200320DEFUN(cfg_sgsn_state_dir, cfg_sgsn_state_dir_cmd,
321 "gtp state-dir PATH",
322 "GTP Parameters\n"
323 "Set the directory for the GTP State file\n"
324 "Local Directory\n")
325{
326 osmo_talloc_replace_string(sgsn, &sgsn->cfg.gtp_statedir, argv[0]);
327
328 return CMD_SUCCESS;
329}
330
Harald Weltee300d002010-06-02 12:41:34 +0200331DEFUN(cfg_sgsn_bind_addr, cfg_sgsn_bind_addr_cmd,
332 "gtp local-ip A.B.C.D",
333 "GTP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100334 "Set the IP address for the local GTP bind for the Gp interface (towards the GGSNs)."
335 " Note: in case you would like to run the GGSN on the same machine as the SGSN, you can not run"
336 " both on the same IP address, since both sides are specified to use the same GTP port numbers"
337 " (" OSMO_STRINGIFY_VAL(GTP1C_PORT) " and " OSMO_STRINGIFY_VAL(GTP1U_PORT) ")."
338 " For example, you could use 127.0.0.1 for the SGSN and 127.0.0.2 for the GGSN in such"
339 " situations.\n"
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100340 "IPv4 Address\n")
Harald Weltee300d002010-06-02 12:41:34 +0200341{
342 inet_aton(argv[0], &g_cfg->gtp_listenaddr.sin_addr);
343
344 return CMD_SUCCESS;
345}
346
Harald Welted193cb32010-05-17 22:58:03 +0200347DEFUN(cfg_ggsn_remote_ip, cfg_ggsn_remote_ip_cmd,
348 "ggsn <0-255> remote-ip A.B.C.D",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100349 GGSN_STR "GGSN Number\n"
350 "Configure this static GGSN to use the specified remote IP address.\n"
351 "IPv4 Address\n")
Harald Welted193cb32010-05-17 22:58:03 +0200352{
353 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200354 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welte288be162010-05-01 16:48:27 +0200355
Harald Welted193cb32010-05-17 22:58:03 +0200356 inet_aton(argv[1], &ggc->remote_addr);
Harald Welte288be162010-05-01 16:48:27 +0200357
Harald Welted193cb32010-05-17 22:58:03 +0200358 return CMD_SUCCESS;
359}
360
361#if 0
362DEFUN(cfg_ggsn_remote_port, cfg_ggsn_remote_port_cmd,
363 "ggsn <0-255> remote-port <0-65535>",
364 "")
365{
366 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200367 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welted193cb32010-05-17 22:58:03 +0200368 uint16_t port = atoi(argv[1]);
369
370}
371#endif
372
373DEFUN(cfg_ggsn_gtp_version, cfg_ggsn_gtp_version_cmd,
374 "ggsn <0-255> gtp-version (0|1)",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100375 GGSN_STR "GGSN Number\n" "GTP Version\n"
376 "Version 0\n" "Version 1\n")
Harald Welted193cb32010-05-17 22:58:03 +0200377{
378 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200379 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welted193cb32010-05-17 22:58:03 +0200380
381 if (atoi(argv[1]))
382 ggc->gtp_version = 1;
383 else
384 ggc->gtp_version = 0;
385
386 return CMD_SUCCESS;
387}
388
Pau Espin Pedrolfa120102018-07-09 20:37:47 +0200389/* Seee 3GPP TS 29.060 section 7.2.1 */
390DEFUN(cfg_ggsn_echo_interval, cfg_ggsn_echo_interval_cmd,
391 "ggsn <0-255> echo-interval <1-36000>",
392 GGSN_STR "GGSN Number\n"
393 "Send an echo request to this static GGSN every interval.\n"
394 "Interval between echo requests in seconds.\n")
395{
396 uint32_t id = atoi(argv[0]);
397 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
398
399 ggc->echo_interval = atoi(argv[1]);
400
401 if (ggc->echo_interval < 60)
Pau Espin Pedrolba2e5002019-05-27 17:35:32 +0200402 vty_out(vty, "%% 3GPP TS 29.060 section 7.2.1 states interval should " \
Pau Espin Pedrolfa120102018-07-09 20:37:47 +0200403 "not be lower than 60 seconds, use this value for " \
404 "testing purposes only!%s", VTY_NEWLINE);
405
Alexander Couzens176a4d22018-09-18 20:07:37 +0200406 sgsn_ggsn_ctx_check_echo_timer(ggc);
Pau Espin Pedrolfa120102018-07-09 20:37:47 +0200407 return CMD_SUCCESS;
408}
409
Pau Espin Pedrola83850c2018-07-10 12:43:59 +0200410DEFUN(cfg_ggsn_no_echo_interval, cfg_ggsn_no_echo_interval_cmd,
411 "ggsn <0-255> no echo-interval",
412 GGSN_STR "GGSN Number\n"
413 NO_STR "Send an echo request to this static GGSN every interval.\n")
414{
415 uint32_t id = atoi(argv[0]);
416 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
417
Pau Espin Pedrolaa89f5d2019-08-28 16:08:45 +0200418 ggc->echo_interval = 0;
Alexander Couzens176a4d22018-09-18 20:07:37 +0200419 sgsn_ggsn_ctx_check_echo_timer(ggc);
Pau Espin Pedrola83850c2018-07-10 12:43:59 +0200420
421 return CMD_SUCCESS;
422}
423
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800424DEFUN(cfg_ggsn_dynamic_lookup, cfg_ggsn_dynamic_lookup_cmd,
425 "ggsn dynamic",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100426 GGSN_STR
427 "Enable dynamic resolving of GGSNs based on DNS resolving the APN name like in a GRX-style setup."
428 " Changing this setting requires a restart.\n")
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800429{
430 sgsn->cfg.dynamic_lookup = 1;
431 return CMD_SUCCESS;
432}
433
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800434DEFUN(cfg_grx_ggsn, cfg_grx_ggsn_cmd,
435 "grx-dns-add A.B.C.D",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100436 "Use the specified IP address for DNS-resolving the AP names to GGSN IP addresses\n"
437 "IPv4 address\n")
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800438{
Pau Espin Pedrolb1d1c242018-10-30 17:27:59 +0100439 struct ares_addr_node *node = talloc_zero(tall_sgsn_ctx, struct ares_addr_node);
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800440 node->family = AF_INET;
441 inet_aton(argv[0], &node->addr.addr4);
442
443 node->next = sgsn->ares_servers;
444 sgsn->ares_servers = node;
445 return CMD_SUCCESS;
446}
447
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100448#define APN_STR "Configure the information per APN\n"
449#define APN_GW_STR "The APN gateway name optionally prefixed by '*' (wildcard)\n"
450
451static int add_apn_ggsn_mapping(struct vty *vty, const char *apn_str,
452 const char *imsi_prefix, int ggsn_id)
453{
454 struct apn_ctx *actx;
455 struct sgsn_ggsn_ctx *ggsn;
456
457 ggsn = sgsn_ggsn_ctx_by_id(ggsn_id);
458 if (ggsn == NULL) {
459 vty_out(vty, "%% a GGSN with id %d has not been defined%s",
460 ggsn_id, VTY_NEWLINE);
461 return CMD_WARNING;
462 }
463
464 actx = sgsn_apn_ctx_find_alloc(apn_str, imsi_prefix);
465 if (!actx) {
466 vty_out(vty, "%% unable to create APN context for %s/%s%s",
467 apn_str, imsi_prefix, VTY_NEWLINE);
468 return CMD_WARNING;
469 }
470
471 actx->ggsn = ggsn;
472
473 return CMD_SUCCESS;
474}
475
Harald Welted193cb32010-05-17 22:58:03 +0200476DEFUN(cfg_apn_ggsn, cfg_apn_ggsn_cmd,
477 "apn APNAME ggsn <0-255>",
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100478 APN_STR APN_GW_STR
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100479 "Select the GGSN to use for the given APN gateway prefix\n"
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100480 "The GGSN id")
Harald Welted193cb32010-05-17 22:58:03 +0200481{
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100482
483 return add_apn_ggsn_mapping(vty, argv[0], "", atoi(argv[1]));
Harald Welted193cb32010-05-17 22:58:03 +0200484}
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100485
486DEFUN(cfg_apn_imsi_ggsn, cfg_apn_imsi_ggsn_cmd,
487 "apn APNAME imsi-prefix IMSIPRE ggsn <0-255>",
488 APN_STR APN_GW_STR
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100489 "Select the GGSN to use for the given APN gateway prefix if and only if the IMSI matches the"
490 " given prefix.\n"
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100491 "An IMSI prefix\n"
492 "Select the GGSN to use when APN gateway and IMSI prefix match\n"
493 "The GGSN id")
494{
495
496 return add_apn_ggsn_mapping(vty, argv[0], argv[1], atoi(argv[2]));
497}
Harald Welted193cb32010-05-17 22:58:03 +0200498
Maxc005db72017-10-27 18:43:29 +0200499char *sgsn_gtp_ntoa(struct ul16_t *ul)
Harald Welte471ac7d2016-12-15 19:48:58 +0100500{
Max8492c202017-12-05 17:28:15 +0100501 struct in_addr ia;
502
503 if (gsna2in_addr(&ia, ul) != 0)
Harald Welte471ac7d2016-12-15 19:48:58 +0100504 return "UNKNOWN";
Max8492c202017-12-05 17:28:15 +0100505
506 return inet_ntoa(ia);
Harald Welte471ac7d2016-12-15 19:48:58 +0100507}
508
Harald Welted193cb32010-05-17 22:58:03 +0200509static void vty_dump_pdp(struct vty *vty, const char *pfx,
510 struct sgsn_pdp_ctx *pdp)
511{
Jacob Erlbeck99985b52014-10-13 10:32:00 +0200512 const char *imsi = pdp->mm ? pdp->mm->imsi : "(detaching)";
Harald Welte471ac7d2016-12-15 19:48:58 +0100513 vty_out(vty, "%sPDP Context IMSI: %s, SAPI: %u, NSAPI: %u, TI: %u%s",
514 pfx, imsi, pdp->sapi, pdp->nsapi, pdp->ti, VTY_NEWLINE);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200515 if (pdp->lib) {
Max7933d962017-10-19 16:52:30 +0200516 char apnbuf[APN_MAXLEN + 1];
Harald Weltedfbd2c82017-08-13 00:56:45 +0200517 vty_out(vty, "%s APN: %s%s", pfx,
Max7933d962017-10-19 16:52:30 +0200518 osmo_apn_to_str(apnbuf, pdp->lib->apn_use.v, pdp->lib->apn_use.l),
Harald Weltedfbd2c82017-08-13 00:56:45 +0200519 VTY_NEWLINE);
520 vty_out(vty, "%s PDP Address: %s%s", pfx,
521 gprs_pdpaddr2str(pdp->lib->eua.v, pdp->lib->eua.l),
522 VTY_NEWLINE);
Maxb24af2b2017-12-05 17:54:42 +0100523 vty_out(vty, "%s GTPv%d Local Control(%s / TEIC: 0x%08x) ", pfx, pdp->lib->version,
Maxc005db72017-10-27 18:43:29 +0200524 sgsn_gtp_ntoa(&pdp->lib->gsnlc), pdp->lib->teic_own);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200525 vty_out(vty, "Data(%s / TEID: 0x%08x)%s",
Maxc005db72017-10-27 18:43:29 +0200526 sgsn_gtp_ntoa(&pdp->lib->gsnlu), pdp->lib->teid_own, VTY_NEWLINE);
Maxb24af2b2017-12-05 17:54:42 +0100527 vty_out(vty, "%s GTPv%d Remote Control(%s / TEIC: 0x%08x) ", pfx, pdp->lib->version,
Maxc005db72017-10-27 18:43:29 +0200528 sgsn_gtp_ntoa(&pdp->lib->gsnrc), pdp->lib->teic_gn);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200529 vty_out(vty, "Data(%s / TEID: 0x%08x)%s",
Maxc005db72017-10-27 18:43:29 +0200530 sgsn_gtp_ntoa(&pdp->lib->gsnru), pdp->lib->teid_gn, VTY_NEWLINE);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200531 }
Harald Welte471ac7d2016-12-15 19:48:58 +0100532
Harald Welteefbdee92010-06-10 00:20:12 +0200533 vty_out_rate_ctr_group(vty, " ", pdp->ctrg);
Harald Welted193cb32010-05-17 22:58:03 +0200534}
535
536static void vty_dump_mmctx(struct vty *vty, const char *pfx,
537 struct sgsn_mm_ctx *mm, int pdp)
538{
Pau Espin Pedrol9119d502019-08-30 17:48:10 +0200539 uint32_t id = 0;
Pau Espin Pedrolfd815bb2019-08-30 18:32:42 +0200540 const char *mm_state_name = NULL;
Pau Espin Pedrol9119d502019-08-30 17:48:10 +0200541
542 switch(mm->ran_type) {
543 case MM_CTX_T_UTRAN_Iu:
544#if BUILD_IU
545 id = mm->iu.ue_ctx->conn_id;
Pau Espin Pedrolfd815bb2019-08-30 18:32:42 +0200546 mm_state_name = osmo_fsm_inst_state_name(mm->iu.mm_state_fsm);
Pau Espin Pedrol9119d502019-08-30 17:48:10 +0200547#endif
548 break;
549 case MM_CTX_T_GERAN_Gb:
550 id = mm->gb.tlli;
Pau Espin Pedrolfd815bb2019-08-30 18:32:42 +0200551 mm_state_name = osmo_fsm_inst_state_name(mm->gb.mm_state_fsm);
Pau Espin Pedrol9119d502019-08-30 17:48:10 +0200552 break;
553 }
554
Harald Welted193cb32010-05-17 22:58:03 +0200555 vty_out(vty, "%sMM Context for IMSI %s, IMEI %s, P-TMSI %08x%s",
556 pfx, mm->imsi, mm->imei, mm->p_tmsi, VTY_NEWLINE);
Holger Hans Peter Freyther8ee13e22015-05-18 10:00:03 +0200557 vty_out(vty, "%s MSISDN: %s, TLLI: %08x%s HLR: %s",
Pau Espin Pedrol9119d502019-08-30 17:48:10 +0200558 pfx, mm->msisdn, id, mm->hlr, VTY_NEWLINE);
Pau Espin Pedrolfd815bb2019-08-30 18:32:42 +0200559 vty_out(vty, "%s GMM State: %s, Routeing Area: %s, Cell ID: %u%s",
Pau Espin Pedrol31c46572019-09-02 16:45:27 +0200560 pfx, osmo_fsm_inst_state_name(mm->gmm_fsm),
Neels Hofmeyr10719b72018-02-21 00:39:36 +0100561 osmo_rai_name(&mm->ra), mm->gb.cell_id, VTY_NEWLINE);
Pau Espin Pedrolfd815bb2019-08-30 18:32:42 +0200562 vty_out(vty, "%s MM State: %s, RAN Type: %s%s", pfx, mm_state_name,
563 get_value_string(sgsn_ran_type_names, mm->ran_type), VTY_NEWLINE);
Harald Welted193cb32010-05-17 22:58:03 +0200564
Pau Espin Pedrol3b848bd2019-08-30 18:06:35 +0200565 vty_out_rate_ctr_group(vty, " ", mm->ctrg);
Harald Welte8acd88f2010-05-18 10:57:45 +0200566
Harald Welted193cb32010-05-17 22:58:03 +0200567 if (pdp) {
568 struct sgsn_pdp_ctx *pdp;
569
570 llist_for_each_entry(pdp, &mm->pdp_list, list)
571 vty_dump_pdp(vty, " ", pdp);
572 }
573}
574
575DEFUN(show_sgsn, show_sgsn_cmd, "show sgsn",
576 SHOW_STR "Display information about the SGSN")
577{
Jacob Erlbeck80547992014-12-19 19:19:46 +0100578 if (sgsn->gsup_client) {
579 struct ipa_client_conn *link = sgsn->gsup_client->link;
580 vty_out(vty,
581 " Remote authorization: %sconnected to %s:%d via GSUP%s",
582 sgsn->gsup_client->is_connected ? "" : "not ",
583 link->addr, link->port,
584 VTY_NEWLINE);
585 }
Maxbaabc682017-10-20 13:39:57 +0200586 if (sgsn->gsn)
587 vty_out(vty, " GSN: signalling %s, user traffic %s%s",
588 inet_ntoa(sgsn->gsn->gsnc), inet_ntoa(sgsn->gsn->gsnu), VTY_NEWLINE);
589
Harald Welted193cb32010-05-17 22:58:03 +0200590 /* FIXME: statistics */
591 return CMD_SUCCESS;
592}
593
594#define MMCTX_STR "MM Context\n"
595#define INCLUDE_PDP_STR "Include PDP Context Information\n"
596
597#if 0
598DEFUN(show_mmctx_tlli, show_mmctx_tlli_cmd,
599 "show mm-context tlli HEX [pdp]",
600 SHOW_STR MMCTX_STR "Identify by TLLI\n" "TLLI\n" INCLUDE_PDP_STR)
601{
602 uint32_t tlli;
603 struct sgsn_mm_ctx *mm;
604
605 tlli = strtoul(argv[0], NULL, 16);
606 mm = sgsn_mm_ctx_by_tlli(tlli);
607 if (!mm) {
608 vty_out(vty, "No MM context for TLLI %08x%s",
609 tlli, VTY_NEWLINE);
610 return CMD_WARNING;
611 }
612 vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
613 return CMD_SUCCESS;
614}
615#endif
616
617DEFUN(swow_mmctx_imsi, show_mmctx_imsi_cmd,
618 "show mm-context imsi IMSI [pdp]",
619 SHOW_STR MMCTX_STR "Identify by IMSI\n" "IMSI of the MM Context\n"
620 INCLUDE_PDP_STR)
621{
622 struct sgsn_mm_ctx *mm;
623
624 mm = sgsn_mm_ctx_by_imsi(argv[0]);
625 if (!mm) {
626 vty_out(vty, "No MM context for IMSI %s%s",
627 argv[0], VTY_NEWLINE);
628 return CMD_WARNING;
629 }
630 vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
631 return CMD_SUCCESS;
632}
633
634DEFUN(swow_mmctx_all, show_mmctx_all_cmd,
635 "show mm-context all [pdp]",
636 SHOW_STR MMCTX_STR "All MM Contexts\n" INCLUDE_PDP_STR)
637{
638 struct sgsn_mm_ctx *mm;
639
640 llist_for_each_entry(mm, &sgsn_mm_ctxts, list)
641 vty_dump_mmctx(vty, "", mm, argv[0] ? 1 : 0);
642
643 return CMD_SUCCESS;
644}
645
Harald Welted193cb32010-05-17 22:58:03 +0200646DEFUN(show_pdpctx_all, show_pdpctx_all_cmd,
647 "show pdp-context all",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100648 SHOW_STR "Display information on PDP Context\n" "Show everything\n")
Harald Welted193cb32010-05-17 22:58:03 +0200649{
650 struct sgsn_pdp_ctx *pdp;
651
652 llist_for_each_entry(pdp, &sgsn_pdp_ctxts, g_list)
653 vty_dump_pdp(vty, "", pdp);
654
655 return CMD_SUCCESS;
656}
Harald Welte288be162010-05-01 16:48:27 +0200657
Harald Welte7f6da482013-03-19 11:00:13 +0100658
659DEFUN(imsi_acl, cfg_imsi_acl_cmd,
660 "imsi-acl (add|del) IMSI",
661 "Access Control List of foreign IMSIs\n"
662 "Add IMSI to ACL\n"
663 "Remove IMSI from ACL\n"
664 "IMSI of subscriber\n")
665{
Maxef38b4c2018-11-20 10:25:53 +0100666 char imsi_sanitized[GSM23003_IMSI_MAX_DIGITS + 1];
Harald Welte7f6da482013-03-19 11:00:13 +0100667 const char *op = argv[0];
Philipp Maier6ee49d82017-02-28 16:53:07 +0100668 const char *imsi = imsi_sanitized;
Maxf4fa6952018-01-15 12:12:51 +0100669 size_t len = strnlen(argv[1], GSM23003_IMSI_MAX_DIGITS + 1);
Harald Welte7f6da482013-03-19 11:00:13 +0100670 int rc;
671
Maxef38b4c2018-11-20 10:25:53 +0100672 memset(imsi_sanitized, '0', GSM23003_IMSI_MAX_DIGITS);
673 imsi_sanitized[GSM23003_IMSI_MAX_DIGITS] = '\0';
674
Philipp Maier6ee49d82017-02-28 16:53:07 +0100675 /* Sanitize IMSI */
Maxf4fa6952018-01-15 12:12:51 +0100676 if (len > GSM23003_IMSI_MAX_DIGITS) {
677 vty_out(vty, "%% IMSI (%s) too long (max %u digits) -- ignored!%s",
678 argv[1], GSM23003_IMSI_MAX_DIGITS, VTY_NEWLINE);
Philipp Maier6ee49d82017-02-28 16:53:07 +0100679 return CMD_WARNING;
680 }
Maxf4fa6952018-01-15 12:12:51 +0100681
682 osmo_strlcpy(imsi_sanitized + GSM23003_IMSI_MAX_DIGITS - len, argv[1],
683 sizeof(imsi_sanitized) - (GSM23003_IMSI_MAX_DIGITS - len));
Philipp Maier6ee49d82017-02-28 16:53:07 +0100684
Harald Welte7f6da482013-03-19 11:00:13 +0100685 if (!strcmp(op, "add"))
Jacob Erlbeck3b5d4072014-10-24 15:11:03 +0200686 rc = sgsn_acl_add(imsi, g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +0100687 else
Jacob Erlbeck3b5d4072014-10-24 15:11:03 +0200688 rc = sgsn_acl_del(imsi, g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +0100689
690 if (rc < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100691 vty_out(vty, "%% unable to %s ACL%s", op, VTY_NEWLINE);
Harald Welte7f6da482013-03-19 11:00:13 +0100692 return CMD_WARNING;
693 }
694
695 return CMD_SUCCESS;
696}
697
Max93408ae2016-06-28 14:10:16 +0200698DEFUN(cfg_encrypt, cfg_encrypt_cmd,
699 "encryption (GEA0|GEA1|GEA2|GEA3|GEA4)",
700 "Set encryption algorithm for SGSN\n"
701 "Use GEA0 (no encryption)\n"
702 "Use GEA1\nUse GEA2\nUse GEA3\nUse GEA4\n")
703{
Max93408ae2016-06-28 14:10:16 +0200704 enum gprs_ciph_algo c = get_string_value(gprs_cipher_names, argv[0]);
Max086067f2017-05-02 13:03:28 +0200705 if (c != GPRS_ALGO_GEA0) {
706 if (!gprs_cipher_supported(c)) {
707 vty_out(vty, "%% cipher %s is unsupported in current version%s", argv[0], VTY_NEWLINE);
708 return CMD_WARNING;
709 }
710
711 if (!g_cfg->require_authentication) {
712 vty_out(vty, "%% unable to use encryption %s without authentication: please adjust auth-policy%s",
713 argv[0], VTY_NEWLINE);
714 return CMD_WARNING;
715 }
Max93408ae2016-06-28 14:10:16 +0200716 }
717
718 g_cfg->cipher = c;
719
720 return CMD_SUCCESS;
721}
722
Vadim Yanitskiy794f4462019-05-27 05:39:06 +0700723DEFUN(cfg_authentication, cfg_authentication_cmd,
724 "authentication (optional|required)",
Pau Espin Pedrold1463bc2019-06-13 19:03:25 +0200725 "Whether to enforce MS authentication in GERAN (only with auth-policy remote)\n"
726 "Allow MS to attach via GERAN without authentication (default and only possible value for non-remote auth-policy)\n"
727 "Always require authentication (only available for auth-policy remote, default with that auth-policy)\n")
Vadim Yanitskiy794f4462019-05-27 05:39:06 +0700728{
729 int required = (argv[0][0] == 'r');
730
731 if (vty->type != VTY_FILE) {
732 if (g_cfg->auth_policy != SGSN_AUTH_POLICY_REMOTE && required) {
733 vty_out(vty, "%% Authentication is not possible without HLR, "
734 "consider setting 'auth-policy' to 'remote'%s",
735 VTY_NEWLINE);
736 return CMD_WARNING;
737 }
738 }
739
740 g_cfg->require_authentication = required;
741 return CMD_SUCCESS;
742}
743
Harald Welte3dfb5492013-03-19 11:48:54 +0100744DEFUN(cfg_auth_policy, cfg_auth_policy_cmd,
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100745 "auth-policy (accept-all|closed|acl-only|remote)",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100746 "Configure the Authorization policy of the SGSN. This setting determines which subscribers are"
747 " permitted to register to the network.\n"
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100748 "Accept all IMSIs (DANGEROUS)\n"
749 "Accept only home network subscribers or those in the ACL\n"
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100750 "Accept only subscribers in the ACL\n"
751 "Use remote subscription data only (HLR)\n")
Harald Welte3dfb5492013-03-19 11:48:54 +0100752{
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100753 int val = get_string_value(sgsn_auth_pol_strs, argv[0]);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100754 OSMO_ASSERT(val >= SGSN_AUTH_POLICY_OPEN && val <= SGSN_AUTH_POLICY_REMOTE);
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100755 g_cfg->auth_policy = val;
Jacob Erlbeck771573c2014-12-19 18:08:48 +0100756 g_cfg->require_update_location = (val == SGSN_AUTH_POLICY_REMOTE);
Harald Welte3dfb5492013-03-19 11:48:54 +0100757
758 return CMD_SUCCESS;
759}
760
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100761/* Subscriber */
Neels Hofmeyr396f2e62017-09-04 15:13:25 +0200762#include <osmocom/sgsn/gprs_subscriber.h>
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100763
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100764static void subscr_dump_full_vty(struct vty *vty, struct gprs_subscr *gsub, int pending)
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100765{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100766#if 0
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100767 char expire_time[200];
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100768#endif
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100769 struct gsm_auth_tuple *at;
770 int at_idx;
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100771 struct sgsn_subscriber_pdp_data *pdp;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100772
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100773 vty_out(vty, " Authorized: %d%s",
774 gsub->authorized, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100775 vty_out(vty, " LAC: %d/0x%x%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100776 gsub->lac, gsub->lac, VTY_NEWLINE);
777 vty_out(vty, " IMSI: %s%s", gsub->imsi, VTY_NEWLINE);
778 if (gsub->tmsi != GSM_RESERVED_TMSI)
779 vty_out(vty, " TMSI: %08X%s", gsub->tmsi,
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100780 VTY_NEWLINE);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100781 if (gsub->sgsn_data->msisdn_len > 0)
Holger Hans Peter Freytherf7b38262015-04-23 16:58:33 -0400782 vty_out(vty, " MSISDN (BCD): %s%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100783 osmo_hexdump(gsub->sgsn_data->msisdn,
784 gsub->sgsn_data->msisdn_len),
Holger Hans Peter Freytherf7b38262015-04-23 16:58:33 -0400785 VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100786
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100787 if (strlen(gsub->imei) > 0)
788 vty_out(vty, " IMEI: %s%s", gsub->imei, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100789
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100790 for (at_idx = 0; at_idx < ARRAY_SIZE(gsub->sgsn_data->auth_triplets);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100791 at_idx++) {
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100792 at = &gsub->sgsn_data->auth_triplets[at_idx];
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100793 if (at->key_seq == GSM_KEY_SEQ_INVAL)
794 continue;
795
796 vty_out(vty, " A3A8 tuple (used %d times): ",
797 at->use_count);
Harald Welte89837d42016-05-06 23:28:11 +0200798 vty_out(vty, " CKSN: %d, ",
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100799 at->key_seq);
Harald Welte89837d42016-05-06 23:28:11 +0200800 if (at->vec.auth_types & OSMO_AUTH_TYPE_GSM) {
801 vty_out(vty, "RAND: %s, ",
Max34604c22019-02-13 14:11:29 +0100802 osmo_hexdump_nospc(at->vec.rand,
Harald Welte89837d42016-05-06 23:28:11 +0200803 sizeof(at->vec.rand)));
804 vty_out(vty, "SRES: %s, ",
Max34604c22019-02-13 14:11:29 +0100805 osmo_hexdump_nospc(at->vec.sres,
Harald Welte89837d42016-05-06 23:28:11 +0200806 sizeof(at->vec.sres)));
807 vty_out(vty, "Kc: %s%s",
Max34604c22019-02-13 14:11:29 +0100808 osmo_hexdump_nospc(at->vec.kc,
Harald Welte89837d42016-05-06 23:28:11 +0200809 sizeof(at->vec.kc)), VTY_NEWLINE);
810 }
811 if (at->vec.auth_types & OSMO_AUTH_TYPE_UMTS) {
812 vty_out(vty, " AUTN: %s, ",
813 osmo_hexdump(at->vec.autn,
814 sizeof(at->vec.autn)));
815 vty_out(vty, "RES: %s, ",
Max34604c22019-02-13 14:11:29 +0100816 osmo_hexdump_nospc(at->vec.res, at->vec.res_len));
Harald Welte89837d42016-05-06 23:28:11 +0200817 vty_out(vty, "IK: %s, ",
Max34604c22019-02-13 14:11:29 +0100818 osmo_hexdump_nospc(at->vec.ik, sizeof(at->vec.ik)));
Harald Welte89837d42016-05-06 23:28:11 +0200819 vty_out(vty, "CK: %s, ",
Max34604c22019-02-13 14:11:29 +0100820 osmo_hexdump_nospc(at->vec.ck, sizeof(at->vec.ck)));
Harald Welte89837d42016-05-06 23:28:11 +0200821 }
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100822 }
823
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100824 llist_for_each_entry(pdp, &gsub->sgsn_data->pdp_list, list) {
Max34604c22019-02-13 14:11:29 +0100825 vty_out(vty, " PDP info: Id: %d, Type: 0x%04x, APN: '%s'",
826 pdp->context_id, pdp->pdp_type, pdp->apn_str);
827
828 if (pdp->qos_subscribed_len)
829 vty_out(vty, " QoS: %s", osmo_hexdump(pdp->qos_subscribed, pdp->qos_subscribed_len));
830
831 vty_out(vty, "%s", VTY_NEWLINE);
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100832 }
833
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100834#if 0
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100835 /* print the expiration time of a subscriber */
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100836 if (gsub->expire_lu) {
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100837 strftime(expire_time, sizeof(expire_time),
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100838 "%a, %d %b %Y %T %z", localtime(&gsub->expire_lu));
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100839 expire_time[sizeof(expire_time) - 1] = '\0';
840 vty_out(vty, " Expiration Time: %s%s", expire_time, VTY_NEWLINE);
841 }
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100842#endif
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100843
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100844 if (gsub->flags)
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100845 vty_out(vty, " Flags: %s%s%s%s%s%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100846 gsub->flags & GPRS_SUBSCRIBER_FIRST_CONTACT ?
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100847 "FIRST_CONTACT " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100848 gsub->flags & GPRS_SUBSCRIBER_CANCELLED ?
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100849 "CANCELLED " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100850 gsub->flags & GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING ?
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100851 "UPDATE_LOCATION_PENDING " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100852 gsub->flags & GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING ?
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100853 "AUTH_INFO_PENDING " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100854 gsub->flags & GPRS_SUBSCRIBER_ENABLE_PURGE ?
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100855 "ENABLE_PURGE " : "",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100856 VTY_NEWLINE);
857
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100858 vty_out(vty, " Use count: %u%s", gsub->use_count, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100859}
860
Neels Hofmeyr1a9414b2018-09-24 18:14:29 +0200861#define RESET_SGSN_STATE_STR \
862 "Remove all known subscribers, MM contexts and flush BSSGP queues." \
863 " Useful only when running tests against the SGSN\n"
864
Alexander Couzensc503f0a2018-08-07 17:50:04 +0200865DEFUN_HIDDEN(reset_sgsn_state,
866 reset_sgsn_state_cmd,
867 "reset sgsn state",
Neels Hofmeyr1a9414b2018-09-24 18:14:29 +0200868 RESET_SGSN_STATE_STR RESET_SGSN_STATE_STR RESET_SGSN_STATE_STR)
Alexander Couzensc503f0a2018-08-07 17:50:04 +0200869{
870 struct gprs_subscr *subscr, *tmp_subscr;
871 struct sgsn_mm_ctx *mm, *tmp_mm;
872
873 llist_for_each_entry_safe(mm, tmp_mm, &sgsn_mm_ctxts, list)
874 {
875 gsm0408_gprs_access_cancelled(mm, SGSN_ERROR_CAUSE_NONE);
876 }
877 vty_out(vty, "Cancelled MM Ctx. %s", VTY_NEWLINE);
878
879 llist_for_each_entry_safe(subscr, tmp_subscr, gprs_subscribers, entry) {
880 gprs_subscr_get(subscr);
881 gprs_subscr_cancel(subscr);
882 gprs_subscr_put(subscr);
883 }
884 vty_out(vty, "Removed all gprs subscribers.%s", VTY_NEWLINE);
885
886 bssgp_flush_all_queues();
887 vty_out(vty, "Flushed all BSSGPs queues.%s", VTY_NEWLINE);
888
Alexander Couzens35c34942018-09-17 04:39:14 +0200889 gtp_clear_queues(sgsn->gsn);
Alexander Couzensa66f0f22018-09-18 16:09:18 +0200890 vty_out(vty, "Flushed rx & tx queus towards the GGSN.%s", VTY_NEWLINE);
Alexander Couzens35c34942018-09-17 04:39:14 +0200891
Alexander Couzensc503f0a2018-08-07 17:50:04 +0200892 /* remove all queues to bssgp */
893 return CMD_SUCCESS;
894}
895
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100896DEFUN(show_subscr_cache,
897 show_subscr_cache_cmd,
898 "show subscriber cache",
899 SHOW_STR "Show information about subscribers\n"
900 "Display contents of subscriber cache\n")
901{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100902 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100903
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100904 llist_for_each_entry(subscr, gprs_subscribers, entry) {
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100905 vty_out(vty, " Subscriber:%s", VTY_NEWLINE);
906 subscr_dump_full_vty(vty, subscr, 0);
907 }
908
909 return CMD_SUCCESS;
910}
911
912#define UPDATE_SUBSCR_STR "update-subscriber imsi IMSI "
913#define UPDATE_SUBSCR_HELP "Update subscriber list\n" \
914 "Use the IMSI to select the subscriber\n" \
915 "The IMSI\n"
916
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100917#define UPDATE_SUBSCR_INSERT_HELP "Insert data into the subscriber record\n"
918
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100919DEFUN(update_subscr_insert_auth_triplet, update_subscr_insert_auth_triplet_cmd,
920 UPDATE_SUBSCR_STR "insert auth-triplet <1-5> sres SRES rand RAND kc KC",
921 UPDATE_SUBSCR_HELP
922 UPDATE_SUBSCR_INSERT_HELP
923 "Update authentication triplet\n"
924 "Triplet index\n"
925 "Set SRES value\nSRES value (4 byte) in hex\n"
926 "Set RAND value\nRAND value (16 byte) in hex\n"
927 "Set Kc value\nKc value (8 byte) in hex\n")
928{
929 const char *imsi = argv[0];
930 const int cksn = atoi(argv[1]) - 1;
931 const char *sres_str = argv[2];
932 const char *rand_str = argv[3];
933 const char *kc_str = argv[4];
934 struct gsm_auth_tuple at = {0,};
935
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100936 struct gprs_subscr *subscr;
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100937
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100938 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100939 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100940 vty_out(vty, "%% unable get subscriber record for %s%s",
941 imsi, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100942 return CMD_WARNING;
943 }
944
945 OSMO_ASSERT(subscr->sgsn_data);
946
Harald Welte121e9a42016-04-20 13:13:19 +0200947 if (osmo_hexparse(sres_str, &at.vec.sres[0], sizeof(at.vec.sres)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100948 vty_out(vty, "%% invalid SRES value '%s'%s",
949 sres_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100950 goto failed;
951 }
Harald Welte121e9a42016-04-20 13:13:19 +0200952 if (osmo_hexparse(rand_str, &at.vec.rand[0], sizeof(at.vec.rand)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100953 vty_out(vty, "%% invalid RAND value '%s'%s",
954 rand_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100955 goto failed;
956 }
Harald Welte121e9a42016-04-20 13:13:19 +0200957 if (osmo_hexparse(kc_str, &at.vec.kc[0], sizeof(at.vec.kc)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100958 vty_out(vty, "%% invalid Kc value '%s'%s",
959 kc_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100960 goto failed;
961 }
962 at.key_seq = cksn;
963
964 subscr->sgsn_data->auth_triplets[cksn] = at;
965 subscr->sgsn_data->auth_triplets_updated = 1;
966
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100967 gprs_subscr_put(subscr);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100968
969 return CMD_SUCCESS;
970
971failed:
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100972 gprs_subscr_put(subscr);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100973 return CMD_SUCCESS;
974}
975
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100976DEFUN(update_subscr_cancel, update_subscr_cancel_cmd,
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100977 UPDATE_SUBSCR_STR "cancel (update-procedure|subscription-withdraw)",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100978 UPDATE_SUBSCR_HELP
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100979 "Cancel (remove) subscriber record\n"
980 "The MS moved to another SGSN\n"
981 "The subscription is no longer valid\n")
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100982{
983 const char *imsi = argv[0];
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100984 const char *cancel_type = argv[1];
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100985
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100986 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100987
988 subscr = gprs_subscr_get_by_imsi(imsi);
989 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100990 vty_out(vty, "%% no subscriber record for %s%s",
991 imsi, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100992 return CMD_WARNING;
993 }
994
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100995 if (strcmp(cancel_type, "update-procedure") == 0)
996 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
997 else
998 subscr->sgsn_data->error_cause = GMM_CAUSE_IMPL_DETACHED;
999
Jacob Erlbeck37139e52015-01-23 13:52:55 +01001000 gprs_subscr_cancel(subscr);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001001 gprs_subscr_put(subscr);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001002
1003 return CMD_SUCCESS;
1004}
1005
Jacob Erlbeckd9193432015-01-19 14:11:46 +01001006DEFUN(update_subscr_create, update_subscr_create_cmd,
1007 UPDATE_SUBSCR_STR "create",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001008 UPDATE_SUBSCR_HELP
Jacob Erlbeckd9193432015-01-19 14:11:46 +01001009 "Create a subscriber entry\n")
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001010{
1011 const char *imsi = argv[0];
1012
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);
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +01001016 if (subscr) {
1017 vty_out(vty, "%% subscriber record already exists for %s%s",
1018 imsi, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001019 return CMD_WARNING;
1020 }
1021
Jacob Erlbeckd9193432015-01-19 14:11:46 +01001022 subscr = gprs_subscr_get_or_create(imsi);
Alexander Couzens3326ba72020-12-09 22:02:55 +01001023 if (!subscr) {
1024 vty_out(vty, "Can not create subscriber. Out of memory.%s", imsi);
1025 return CMD_WARNING;
1026 }
Jacob Erlbeckd9193432015-01-19 14:11:46 +01001027 subscr->keep_in_ram = 1;
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 Erlbecke988ae42015-01-27 12:41:19 +01001033DEFUN(update_subscr_destroy, update_subscr_destroy_cmd,
1034 UPDATE_SUBSCR_STR "destroy",
1035 UPDATE_SUBSCR_HELP
1036 "Destroy a subscriber entry\n")
1037{
1038 const char *imsi = argv[0];
1039
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001040 struct gprs_subscr *subscr;
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001041
1042 subscr = gprs_subscr_get_by_imsi(imsi);
1043 if (!subscr) {
1044 vty_out(vty, "%% subscriber record does not exist for %s%s",
1045 imsi, VTY_NEWLINE);
1046 return CMD_WARNING;
1047 }
1048
1049 subscr->keep_in_ram = 0;
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +01001050 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001051 gprs_subscr_cancel(subscr);
1052 if (subscr->use_count > 1)
1053 vty_out(vty, "%% subscriber is still in use%s",
1054 VTY_NEWLINE);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001055 gprs_subscr_put(subscr);
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001056
1057 return CMD_SUCCESS;
1058}
1059
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001060#define UL_ERR_STR "system-failure|data-missing|unexpected-data-value|" \
1061 "unknown-subscriber|roaming-not-allowed"
1062
1063#define UL_ERR_HELP \
1064 "Force error code SystemFailure\n" \
1065 "Force error code DataMissing\n" \
1066 "Force error code UnexpectedDataValue\n" \
1067 "Force error code UnknownSubscriber\n" \
1068 "Force error code RoamingNotAllowed\n"
1069
1070DEFUN(update_subscr_update_location_result, update_subscr_update_location_result_cmd,
1071 UPDATE_SUBSCR_STR "update-location-result (ok|" UL_ERR_STR ")",
1072 UPDATE_SUBSCR_HELP
1073 "Complete the update location procedure\n"
1074 "The update location request succeeded\n"
1075 UL_ERR_HELP)
1076{
1077 const char *imsi = argv[0];
1078 const char *ret_code_str = argv[1];
1079
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001080 struct gprs_subscr *subscr;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001081
Jacob Erlbeckd6267d12015-01-19 11:10:04 +01001082 const struct value_string cause_mapping[] = {
1083 { GMM_CAUSE_NET_FAIL, "system-failure" },
1084 { GMM_CAUSE_INV_MAND_INFO, "data-missing" },
1085 { GMM_CAUSE_PROTO_ERR_UNSPEC, "unexpected-data-value" },
1086 { GMM_CAUSE_IMSI_UNKNOWN, "unknown-subscriber" },
1087 { GMM_CAUSE_GPRS_NOTALLOWED, "roaming-not-allowed" },
1088 { 0, NULL }
1089 };
1090
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001091 subscr = gprs_subscr_get_by_imsi(imsi);
1092 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +01001093 vty_out(vty, "%% unable to get subscriber record for %s%s",
1094 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001095 return CMD_WARNING;
1096 }
Jacob Erlbeckd6267d12015-01-19 11:10:04 +01001097
1098 if (strcmp(ret_code_str, "ok") == 0) {
1099 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001100 subscr->authorized = 1;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +01001101 } else {
1102 subscr->sgsn_data->error_cause =
1103 get_string_value(cause_mapping, ret_code_str);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001104 subscr->authorized = 0;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +01001105 }
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001106
1107 gprs_subscr_update(subscr);
1108
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001109 gprs_subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001110
1111 return CMD_SUCCESS;
1112}
1113
1114DEFUN(update_subscr_update_auth_info, update_subscr_update_auth_info_cmd,
1115 UPDATE_SUBSCR_STR "update-auth-info",
1116 UPDATE_SUBSCR_HELP
1117 "Complete the send authentication info procedure\n")
1118{
1119 const char *imsi = argv[0];
1120
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001121 struct gprs_subscr *subscr;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001122
1123 subscr = gprs_subscr_get_by_imsi(imsi);
1124 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +01001125 vty_out(vty, "%% unable to get subscriber record for %s%s",
1126 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001127 return CMD_WARNING;
1128 }
1129
1130 gprs_subscr_update_auth_info(subscr);
1131
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001132 gprs_subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001133
1134 return CMD_SUCCESS;
1135}
1136
Stefan Sperling88220092018-12-11 14:42:00 +01001137DEFUN(cfg_gsup_ipa_name,
1138 cfg_gsup_ipa_name_cmd,
1139 "gsup ipa-name NAME",
1140 "GSUP Parameters\n"
1141 "Set the IPA name of this SGSN\n"
1142 "A unique name for this SGSN. For example: PLMN + redundancy server number: SGSN-901-70-0. "
1143 "This name is used for GSUP routing and must be set if more than one SGSN is connected to the network. "
1144 "The default is 'SGSN-00-00-00-00-00-00'.\n")
1145{
1146 if (vty->type != VTY_FILE) {
1147 vty_out(vty, "The IPA name cannot be changed at run-time; "
1148 "It can only be set in the configuraton file.%s", VTY_NEWLINE);
1149 return CMD_WARNING;
1150 }
1151
1152 g_cfg->sgsn_ipa_name = talloc_strdup(tall_vty_ctx, argv[0]);
1153 return CMD_SUCCESS;
1154}
1155
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001156DEFUN(cfg_gsup_remote_ip, cfg_gsup_remote_ip_cmd,
1157 "gsup remote-ip A.B.C.D",
1158 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001159 "Set the IP address of the remote GSUP server (e.g. OsmoHLR)."
1160 " This setting only applies if 'auth-policy remote' is used.\n"
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001161 "IPv4 Address\n")
1162{
1163 inet_aton(argv[0], &g_cfg->gsup_server_addr.sin_addr);
1164
1165 return CMD_SUCCESS;
1166}
1167
1168DEFUN(cfg_gsup_remote_port, cfg_gsup_remote_port_cmd,
1169 "gsup remote-port <0-65535>",
1170 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001171 "Set the TCP port of the remote GSUP server, see also 'gsup remote-ip'\n"
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001172 "Remote TCP port\n")
1173{
1174 g_cfg->gsup_server_port = atoi(argv[0]);
1175
1176 return CMD_SUCCESS;
1177}
1178
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001179DEFUN(cfg_gsup_oap_id, cfg_gsup_oap_id_cmd,
1180 "gsup oap-id <0-65535>",
1181 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001182 "Set the OAP client ID for authentication on the GSUP protocol."
1183 " This setting only applies if 'auth-policy remote' is used.\n"
1184 "OAP client ID (0 == disabled)\n")
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001185{
1186 /* VTY ensures range */
1187 g_cfg->oap.client_id = (uint16_t)atoi(argv[0]);
1188 return CMD_SUCCESS;
1189}
1190
1191DEFUN(cfg_gsup_oap_k, cfg_gsup_oap_k_cmd,
1192 "gsup oap-k K",
1193 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001194 "Set the OAP shared secret key K for authentication on the GSUP protocol."
1195 " This setting only applies if auth-policy remote is used.\n"
1196 "K value (16 byte) hex\n")
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001197{
1198 const char *k = argv[0];
1199
1200 g_cfg->oap.secret_k_present = 0;
1201
1202 if ((!k) || (strlen(k) == 0))
1203 goto disable;
1204
1205 int k_len = osmo_hexparse(k,
1206 g_cfg->oap.secret_k,
1207 sizeof(g_cfg->oap.secret_k));
1208 if (k_len != 16) {
1209 vty_out(vty, "%% need exactly 16 octets for oap-k, got %d.%s",
1210 k_len, VTY_NEWLINE);
1211 goto disable;
1212 }
1213
1214 g_cfg->oap.secret_k_present = 1;
1215 return CMD_SUCCESS;
1216
1217disable:
1218 if (g_cfg->oap.client_id > 0) {
1219 vty_out(vty, "%% OAP client ID set, but invalid oap-k value disables OAP.%s",
1220 VTY_NEWLINE);
1221 return CMD_WARNING;
1222 }
1223 return CMD_SUCCESS;
1224}
1225
1226DEFUN(cfg_gsup_oap_opc, cfg_gsup_oap_opc_cmd,
1227 "gsup oap-opc OPC",
1228 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001229 "Set the OAP shared secret OPC for authentication on the GSUP protocol."
1230 " This setting only applies if auth-policy remote is used.\n"
1231 "OPC value (16 byte) hex\n")
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001232{
1233 const char *opc = argv[0];
1234
1235 g_cfg->oap.secret_opc_present = 0;
1236
1237 if ((!opc) || (strlen(opc) == 0))
1238 goto disable;
1239
1240 int opc_len = osmo_hexparse(opc,
1241 g_cfg->oap.secret_opc,
1242 sizeof(g_cfg->oap.secret_opc));
1243 if (opc_len != 16) {
1244 vty_out(vty, "%% need exactly 16 octets for oap-opc, got %d.%s",
1245 opc_len, VTY_NEWLINE);
1246 goto disable;
1247 }
1248
1249 g_cfg->oap.secret_opc_present = 1;
1250 return CMD_SUCCESS;
1251
1252disable:
1253 if (g_cfg->oap.client_id > 0) {
1254 vty_out(vty, "%% OAP client ID set, but invalid oap-opc value disables OAP.%s",
1255 VTY_NEWLINE);
1256 return CMD_WARNING;
1257 }
1258 return CMD_SUCCESS;
1259}
1260
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001261DEFUN(cfg_apn_name, cfg_apn_name_cmd,
1262 "access-point-name NAME",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001263 "Globally allow the given APN name for all subscribers.\n"
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001264 "Add this NAME to the list\n")
1265{
1266 return add_apn_ggsn_mapping(vty, argv[0], "", 0);
1267}
1268
1269DEFUN(cfg_no_apn_name, cfg_no_apn_name_cmd,
1270 "no access-point-name NAME",
1271 NO_STR "Configure a global list of allowed APNs\n"
1272 "Remove entry with NAME\n")
1273{
1274 struct apn_ctx *apn_ctx = sgsn_apn_ctx_by_name(argv[0], "");
1275 if (!apn_ctx)
1276 return CMD_SUCCESS;
1277
1278 sgsn_apn_ctx_free(apn_ctx);
1279 return CMD_SUCCESS;
1280}
1281
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001282DEFUN(cfg_cdr_filename, cfg_cdr_filename_cmd,
1283 "cdr filename NAME",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001284 "CDR\n"
1285 "Set the file name for the call-data-record file, logging the data usage of each subscriber.\n"
1286 "filename\n")
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001287{
1288 talloc_free(g_cfg->cdr.filename);
1289 g_cfg->cdr.filename = talloc_strdup(tall_vty_ctx, argv[0]);
1290 return CMD_SUCCESS;
1291}
1292
1293DEFUN(cfg_no_cdr_filename, cfg_no_cdr_filename_cmd,
1294 "no cdr filename",
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +01001295 NO_STR "CDR\nDisable saving CDR to file\n")
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001296{
1297 talloc_free(g_cfg->cdr.filename);
1298 g_cfg->cdr.filename = NULL;
1299 return CMD_SUCCESS;
1300}
1301
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +01001302DEFUN(cfg_cdr_trap, cfg_cdr_trap_cmd,
1303 "cdr trap",
1304 "CDR\nEnable sending CDR via TRAP CTRL messages\n")
1305{
1306 g_cfg->cdr.trap = true;
1307 return CMD_SUCCESS;
1308}
1309
1310DEFUN(cfg_no_cdr_trap, cfg_no_cdr_trap_cmd,
1311 "no cdr trap",
1312 NO_STR "CDR\nDisable sending CDR via TRAP CTRL messages\n")
1313{
1314 g_cfg->cdr.trap = false;
1315 return CMD_SUCCESS;
1316}
1317
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001318DEFUN(cfg_cdr_interval, cfg_cdr_interval_cmd,
1319 "cdr interval <1-2147483647>",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001320 "CDR\n"
1321 "Set the interval for the call-data-record file\n"
1322 "interval in seconds\n")
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001323{
1324 g_cfg->cdr.interval = atoi(argv[0]);
1325 return CMD_SUCCESS;
1326}
1327
Philippf1f34362016-08-26 17:00:21 +02001328#define COMPRESSION_STR "Configure compression\n"
1329DEFUN(cfg_no_comp_rfc1144, cfg_no_comp_rfc1144_cmd,
1330 "no compression rfc1144",
1331 NO_STR COMPRESSION_STR "disable rfc1144 TCP/IP header compression\n")
1332{
1333 g_cfg->pcomp_rfc1144.active = 0;
1334 g_cfg->pcomp_rfc1144.passive = 0;
1335 return CMD_SUCCESS;
1336}
1337
1338DEFUN(cfg_comp_rfc1144, cfg_comp_rfc1144_cmd,
1339 "compression rfc1144 active slots <1-256>",
1340 COMPRESSION_STR
Ruben Undheim55fcf112018-09-25 22:59:34 +02001341 "RFC1144 Header compression scheme\n"
Philippf1f34362016-08-26 17:00:21 +02001342 "Compression is actively proposed\n"
1343 "Number of compression state slots\n"
1344 "Number of compression state slots\n")
1345{
1346 g_cfg->pcomp_rfc1144.active = 1;
1347 g_cfg->pcomp_rfc1144.passive = 1;
1348 g_cfg->pcomp_rfc1144.s01 = atoi(argv[0]) - 1;
1349 return CMD_SUCCESS;
1350}
1351
1352DEFUN(cfg_comp_rfc1144p, cfg_comp_rfc1144p_cmd,
1353 "compression rfc1144 passive",
1354 COMPRESSION_STR
Ruben Undheim55fcf112018-09-25 22:59:34 +02001355 "RFC1144 Header compression scheme\n"
Philippf1f34362016-08-26 17:00:21 +02001356 "Compression is available on request\n")
1357{
1358 g_cfg->pcomp_rfc1144.active = 0;
1359 g_cfg->pcomp_rfc1144.passive = 1;
1360 return CMD_SUCCESS;
1361}
1362
Philipp73f83d52016-09-02 13:38:01 +02001363DEFUN(cfg_no_comp_v42bis, cfg_no_comp_v42bis_cmd,
1364 "no compression v42bis",
1365 NO_STR COMPRESSION_STR "disable V.42bis data compression\n")
1366{
1367 g_cfg->dcomp_v42bis.active = 0;
1368 g_cfg->dcomp_v42bis.passive = 0;
1369 return CMD_SUCCESS;
1370}
1371
1372DEFUN(cfg_comp_v42bis, cfg_comp_v42bis_cmd,
1373 "compression v42bis active direction (ms|sgsn|both) codewords <512-65535> strlen <6-250>",
1374 COMPRESSION_STR
Ruben Undheim55fcf112018-09-25 22:59:34 +02001375 "V.42bis data compression scheme\n"
Philipp73f83d52016-09-02 13:38:01 +02001376 "Compression is actively proposed\n"
1377 "Direction in which the compression shall be active (p0)\n"
1378 "Compress ms->sgsn direction only\n"
1379 "Compress sgsn->ms direction only\n"
1380 "Both directions\n"
1381 "Number of codewords (p1)\n"
1382 "Number of codewords\n"
1383 "Maximum string length (p2)\n" "Maximum string length\n")
1384{
1385 g_cfg->dcomp_v42bis.active = 1;
1386 g_cfg->dcomp_v42bis.passive = 1;
1387
1388 switch (argv[0][0]) {
1389 case 'm':
1390 g_cfg->dcomp_v42bis.p0 = 1;
1391 break;
1392 case 's':
1393 g_cfg->dcomp_v42bis.p0 = 2;
1394 break;
1395 case 'b':
1396 g_cfg->dcomp_v42bis.p0 = 3;
1397 break;
1398 }
1399
1400 g_cfg->dcomp_v42bis.p1 = atoi(argv[1]);
1401 g_cfg->dcomp_v42bis.p2 = atoi(argv[2]);
1402 return CMD_SUCCESS;
1403}
1404
1405DEFUN(cfg_comp_v42bisp, cfg_comp_v42bisp_cmd,
1406 "compression v42bis passive",
1407 COMPRESSION_STR
Ruben Undheim55fcf112018-09-25 22:59:34 +02001408 "V.42bis data compression scheme\n"
Philipp73f83d52016-09-02 13:38:01 +02001409 "Compression is available on request\n")
1410{
1411 g_cfg->dcomp_v42bis.active = 0;
1412 g_cfg->dcomp_v42bis.passive = 1;
1413 return CMD_SUCCESS;
1414}
1415
Pau Espin Pedrol2c908992019-08-19 19:06:06 +02001416#if BUILD_IU
1417DEFUN(cfg_sgsn_cs7_instance_iu,
1418 cfg_sgsn_cs7_instance_iu_cmd,
1419 "cs7-instance-iu <0-15>",
1420 "Set SS7 to be used by the Iu-Interface.\n" "SS7 instance reference number (default: 0)\n")
1421{
1422 g_cfg->iu.cs7_instance = atoi(argv[0]);
1423 return CMD_SUCCESS;
1424}
1425#endif
1426
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001427int sgsn_vty_init(struct sgsn_config *cfg)
Harald Welte288be162010-05-01 16:48:27 +02001428{
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001429 g_cfg = cfg;
1430
Pau Espin Pedrola299d652019-08-14 19:11:10 +02001431 g_cfg->T_defs = sgsn_T_defs;
1432 osmo_tdefs_reset(g_cfg->T_defs);
1433
Harald Welted193cb32010-05-17 22:58:03 +02001434 install_element_ve(&show_sgsn_cmd);
1435 //install_element_ve(&show_mmctx_tlli_cmd);
1436 install_element_ve(&show_mmctx_imsi_cmd);
1437 install_element_ve(&show_mmctx_all_cmd);
1438 install_element_ve(&show_pdpctx_all_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001439 install_element_ve(&show_subscr_cache_cmd);
Pau Espin Pedrola299d652019-08-14 19:11:10 +02001440 install_element_ve(&show_timer_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001441
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01001442 install_element(ENABLE_NODE, &update_subscr_insert_auth_triplet_cmd);
Jacob Erlbeckd9193432015-01-19 14:11:46 +01001443 install_element(ENABLE_NODE, &update_subscr_create_cmd);
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001444 install_element(ENABLE_NODE, &update_subscr_destroy_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001445 install_element(ENABLE_NODE, &update_subscr_cancel_cmd);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001446 install_element(ENABLE_NODE, &update_subscr_update_location_result_cmd);
1447 install_element(ENABLE_NODE, &update_subscr_update_auth_info_cmd);
Alexander Couzensc503f0a2018-08-07 17:50:04 +02001448 install_element(ENABLE_NODE, &reset_sgsn_state_cmd);
Harald Welte288be162010-05-01 16:48:27 +02001449
1450 install_element(CONFIG_NODE, &cfg_sgsn_cmd);
1451 install_node(&sgsn_node, config_write_sgsn);
Keithc70e8382020-10-19 22:24:48 +02001452 install_element(SGSN_NODE, &cfg_sgsn_state_dir_cmd);
Harald Weltee300d002010-06-02 12:41:34 +02001453 install_element(SGSN_NODE, &cfg_sgsn_bind_addr_cmd);
Harald Welted193cb32010-05-17 22:58:03 +02001454 install_element(SGSN_NODE, &cfg_ggsn_remote_ip_cmd);
1455 //install_element(SGSN_NODE, &cfg_ggsn_remote_port_cmd);
1456 install_element(SGSN_NODE, &cfg_ggsn_gtp_version_cmd);
Pau Espin Pedrolfa120102018-07-09 20:37:47 +02001457 install_element(SGSN_NODE, &cfg_ggsn_echo_interval_cmd);
Pau Espin Pedrola83850c2018-07-10 12:43:59 +02001458 install_element(SGSN_NODE, &cfg_ggsn_no_echo_interval_cmd);
Harald Welte7f6da482013-03-19 11:00:13 +01001459 install_element(SGSN_NODE, &cfg_imsi_acl_cmd);
Harald Welte3dfb5492013-03-19 11:48:54 +01001460 install_element(SGSN_NODE, &cfg_auth_policy_cmd);
Vadim Yanitskiy794f4462019-05-27 05:39:06 +07001461 install_element(SGSN_NODE, &cfg_authentication_cmd);
Max93408ae2016-06-28 14:10:16 +02001462 install_element(SGSN_NODE, &cfg_encrypt_cmd);
Stefan Sperling88220092018-12-11 14:42:00 +01001463 install_element(SGSN_NODE, &cfg_gsup_ipa_name_cmd);
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001464 install_element(SGSN_NODE, &cfg_gsup_remote_ip_cmd);
1465 install_element(SGSN_NODE, &cfg_gsup_remote_port_cmd);
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001466 install_element(SGSN_NODE, &cfg_gsup_oap_id_cmd);
1467 install_element(SGSN_NODE, &cfg_gsup_oap_k_cmd);
1468 install_element(SGSN_NODE, &cfg_gsup_oap_opc_cmd);
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +01001469 install_element(SGSN_NODE, &cfg_apn_ggsn_cmd);
1470 install_element(SGSN_NODE, &cfg_apn_imsi_ggsn_cmd);
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001471 install_element(SGSN_NODE, &cfg_apn_name_cmd);
1472 install_element(SGSN_NODE, &cfg_no_apn_name_cmd);
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001473 install_element(SGSN_NODE, &cfg_cdr_filename_cmd);
1474 install_element(SGSN_NODE, &cfg_no_cdr_filename_cmd);
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +01001475 install_element(SGSN_NODE, &cfg_cdr_trap_cmd);
1476 install_element(SGSN_NODE, &cfg_no_cdr_trap_cmd);
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001477 install_element(SGSN_NODE, &cfg_cdr_interval_cmd);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001478 install_element(SGSN_NODE, &cfg_ggsn_dynamic_lookup_cmd);
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +08001479 install_element(SGSN_NODE, &cfg_grx_ggsn_cmd);
Harald Welte288be162010-05-01 16:48:27 +02001480
Pau Espin Pedrola299d652019-08-14 19:11:10 +02001481 install_element(SGSN_NODE, &cfg_sgsn_timer_cmd);
Harald Welte94508822015-08-15 19:08:21 +02001482
Philippf1f34362016-08-26 17:00:21 +02001483 install_element(SGSN_NODE, &cfg_no_comp_rfc1144_cmd);
1484 install_element(SGSN_NODE, &cfg_comp_rfc1144_cmd);
1485 install_element(SGSN_NODE, &cfg_comp_rfc1144p_cmd);
Philipp73f83d52016-09-02 13:38:01 +02001486 install_element(SGSN_NODE, &cfg_no_comp_v42bis_cmd);
1487 install_element(SGSN_NODE, &cfg_comp_v42bis_cmd);
1488 install_element(SGSN_NODE, &cfg_comp_v42bisp_cmd);
Neels Hofmeyr2188a772016-05-20 21:59:55 +02001489
1490#ifdef BUILD_IU
Pau Espin Pedrol2c908992019-08-19 19:06:06 +02001491 install_element(SGSN_NODE, &cfg_sgsn_cs7_instance_iu_cmd);
Neels Hofmeyra7a39472017-07-05 15:19:52 +02001492 ranap_iu_vty_init(SGSN_NODE, &g_cfg->iu.rab_assign_addr_enc);
Neels Hofmeyr2188a772016-05-20 21:59:55 +02001493#endif
Harald Welte288be162010-05-01 16:48:27 +02001494 return 0;
1495}
1496
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001497int sgsn_parse_config(const char *config_file)
Harald Welte288be162010-05-01 16:48:27 +02001498{
1499 int rc;
1500
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001501 /* make sure sgsn_vty_init() was called before this */
1502 OSMO_ASSERT(g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +01001503
Harald Weltedcccb182010-05-16 20:52:23 +02001504 rc = vty_read_config_file(config_file, NULL);
Harald Welte288be162010-05-01 16:48:27 +02001505 if (rc < 0) {
1506 fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
1507 return rc;
1508 }
1509
Neels Hofmeyr27355c92017-02-24 06:28:31 +01001510 if (g_cfg->auth_policy == SGSN_AUTH_POLICY_REMOTE
1511 && !(g_cfg->gsup_server_addr.sin_addr.s_addr
1512 && g_cfg->gsup_server_port)) {
1513 fprintf(stderr, "Configuration error:"
1514 " 'auth-policy remote' requires both"
1515 " 'gsup remote-ip' and 'gsup remote-port'\n");
1516 return -EINVAL;
1517 }
1518
Harald Welte288be162010-05-01 16:48:27 +02001519 return 0;
1520}