blob: 33a652c9f2da770c715245076835ee7fde9e97de [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>
Harald Welteea34a4e2012-06-16 14:59:56 +080037#include <osmocom/gprs/gprs_ns.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);
1023 subscr->keep_in_ram = 1;
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001024 gprs_subscr_put(subscr);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001025
1026 return CMD_SUCCESS;
1027}
1028
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001029DEFUN(update_subscr_destroy, update_subscr_destroy_cmd,
1030 UPDATE_SUBSCR_STR "destroy",
1031 UPDATE_SUBSCR_HELP
1032 "Destroy a subscriber entry\n")
1033{
1034 const char *imsi = argv[0];
1035
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001036 struct gprs_subscr *subscr;
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001037
1038 subscr = gprs_subscr_get_by_imsi(imsi);
1039 if (!subscr) {
1040 vty_out(vty, "%% subscriber record does not exist for %s%s",
1041 imsi, VTY_NEWLINE);
1042 return CMD_WARNING;
1043 }
1044
1045 subscr->keep_in_ram = 0;
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +01001046 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001047 gprs_subscr_cancel(subscr);
1048 if (subscr->use_count > 1)
1049 vty_out(vty, "%% subscriber is still in use%s",
1050 VTY_NEWLINE);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001051 gprs_subscr_put(subscr);
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001052
1053 return CMD_SUCCESS;
1054}
1055
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001056#define UL_ERR_STR "system-failure|data-missing|unexpected-data-value|" \
1057 "unknown-subscriber|roaming-not-allowed"
1058
1059#define UL_ERR_HELP \
1060 "Force error code SystemFailure\n" \
1061 "Force error code DataMissing\n" \
1062 "Force error code UnexpectedDataValue\n" \
1063 "Force error code UnknownSubscriber\n" \
1064 "Force error code RoamingNotAllowed\n"
1065
1066DEFUN(update_subscr_update_location_result, update_subscr_update_location_result_cmd,
1067 UPDATE_SUBSCR_STR "update-location-result (ok|" UL_ERR_STR ")",
1068 UPDATE_SUBSCR_HELP
1069 "Complete the update location procedure\n"
1070 "The update location request succeeded\n"
1071 UL_ERR_HELP)
1072{
1073 const char *imsi = argv[0];
1074 const char *ret_code_str = argv[1];
1075
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001076 struct gprs_subscr *subscr;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001077
Jacob Erlbeckd6267d12015-01-19 11:10:04 +01001078 const struct value_string cause_mapping[] = {
1079 { GMM_CAUSE_NET_FAIL, "system-failure" },
1080 { GMM_CAUSE_INV_MAND_INFO, "data-missing" },
1081 { GMM_CAUSE_PROTO_ERR_UNSPEC, "unexpected-data-value" },
1082 { GMM_CAUSE_IMSI_UNKNOWN, "unknown-subscriber" },
1083 { GMM_CAUSE_GPRS_NOTALLOWED, "roaming-not-allowed" },
1084 { 0, NULL }
1085 };
1086
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001087 subscr = gprs_subscr_get_by_imsi(imsi);
1088 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +01001089 vty_out(vty, "%% unable to get subscriber record for %s%s",
1090 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001091 return CMD_WARNING;
1092 }
Jacob Erlbeckd6267d12015-01-19 11:10:04 +01001093
1094 if (strcmp(ret_code_str, "ok") == 0) {
1095 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001096 subscr->authorized = 1;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +01001097 } else {
1098 subscr->sgsn_data->error_cause =
1099 get_string_value(cause_mapping, ret_code_str);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001100 subscr->authorized = 0;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +01001101 }
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001102
1103 gprs_subscr_update(subscr);
1104
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001105 gprs_subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001106
1107 return CMD_SUCCESS;
1108}
1109
1110DEFUN(update_subscr_update_auth_info, update_subscr_update_auth_info_cmd,
1111 UPDATE_SUBSCR_STR "update-auth-info",
1112 UPDATE_SUBSCR_HELP
1113 "Complete the send authentication info procedure\n")
1114{
1115 const char *imsi = argv[0];
1116
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001117 struct gprs_subscr *subscr;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001118
1119 subscr = gprs_subscr_get_by_imsi(imsi);
1120 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +01001121 vty_out(vty, "%% unable to get subscriber record for %s%s",
1122 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001123 return CMD_WARNING;
1124 }
1125
1126 gprs_subscr_update_auth_info(subscr);
1127
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001128 gprs_subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001129
1130 return CMD_SUCCESS;
1131}
1132
Stefan Sperling88220092018-12-11 14:42:00 +01001133DEFUN(cfg_gsup_ipa_name,
1134 cfg_gsup_ipa_name_cmd,
1135 "gsup ipa-name NAME",
1136 "GSUP Parameters\n"
1137 "Set the IPA name of this SGSN\n"
1138 "A unique name for this SGSN. For example: PLMN + redundancy server number: SGSN-901-70-0. "
1139 "This name is used for GSUP routing and must be set if more than one SGSN is connected to the network. "
1140 "The default is 'SGSN-00-00-00-00-00-00'.\n")
1141{
1142 if (vty->type != VTY_FILE) {
1143 vty_out(vty, "The IPA name cannot be changed at run-time; "
1144 "It can only be set in the configuraton file.%s", VTY_NEWLINE);
1145 return CMD_WARNING;
1146 }
1147
1148 g_cfg->sgsn_ipa_name = talloc_strdup(tall_vty_ctx, argv[0]);
1149 return CMD_SUCCESS;
1150}
1151
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001152DEFUN(cfg_gsup_remote_ip, cfg_gsup_remote_ip_cmd,
1153 "gsup remote-ip A.B.C.D",
1154 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001155 "Set the IP address of the remote GSUP server (e.g. OsmoHLR)."
1156 " This setting only applies if 'auth-policy remote' is used.\n"
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001157 "IPv4 Address\n")
1158{
1159 inet_aton(argv[0], &g_cfg->gsup_server_addr.sin_addr);
1160
1161 return CMD_SUCCESS;
1162}
1163
1164DEFUN(cfg_gsup_remote_port, cfg_gsup_remote_port_cmd,
1165 "gsup remote-port <0-65535>",
1166 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001167 "Set the TCP port of the remote GSUP server, see also 'gsup remote-ip'\n"
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001168 "Remote TCP port\n")
1169{
1170 g_cfg->gsup_server_port = atoi(argv[0]);
1171
1172 return CMD_SUCCESS;
1173}
1174
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001175DEFUN(cfg_gsup_oap_id, cfg_gsup_oap_id_cmd,
1176 "gsup oap-id <0-65535>",
1177 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001178 "Set the OAP client ID for authentication on the GSUP protocol."
1179 " This setting only applies if 'auth-policy remote' is used.\n"
1180 "OAP client ID (0 == disabled)\n")
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001181{
1182 /* VTY ensures range */
1183 g_cfg->oap.client_id = (uint16_t)atoi(argv[0]);
1184 return CMD_SUCCESS;
1185}
1186
1187DEFUN(cfg_gsup_oap_k, cfg_gsup_oap_k_cmd,
1188 "gsup oap-k K",
1189 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001190 "Set the OAP shared secret key K for authentication on the GSUP protocol."
1191 " This setting only applies if auth-policy remote is used.\n"
1192 "K value (16 byte) hex\n")
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001193{
1194 const char *k = argv[0];
1195
1196 g_cfg->oap.secret_k_present = 0;
1197
1198 if ((!k) || (strlen(k) == 0))
1199 goto disable;
1200
1201 int k_len = osmo_hexparse(k,
1202 g_cfg->oap.secret_k,
1203 sizeof(g_cfg->oap.secret_k));
1204 if (k_len != 16) {
1205 vty_out(vty, "%% need exactly 16 octets for oap-k, got %d.%s",
1206 k_len, VTY_NEWLINE);
1207 goto disable;
1208 }
1209
1210 g_cfg->oap.secret_k_present = 1;
1211 return CMD_SUCCESS;
1212
1213disable:
1214 if (g_cfg->oap.client_id > 0) {
1215 vty_out(vty, "%% OAP client ID set, but invalid oap-k value disables OAP.%s",
1216 VTY_NEWLINE);
1217 return CMD_WARNING;
1218 }
1219 return CMD_SUCCESS;
1220}
1221
1222DEFUN(cfg_gsup_oap_opc, cfg_gsup_oap_opc_cmd,
1223 "gsup oap-opc OPC",
1224 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001225 "Set the OAP shared secret OPC for authentication on the GSUP protocol."
1226 " This setting only applies if auth-policy remote is used.\n"
1227 "OPC value (16 byte) hex\n")
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001228{
1229 const char *opc = argv[0];
1230
1231 g_cfg->oap.secret_opc_present = 0;
1232
1233 if ((!opc) || (strlen(opc) == 0))
1234 goto disable;
1235
1236 int opc_len = osmo_hexparse(opc,
1237 g_cfg->oap.secret_opc,
1238 sizeof(g_cfg->oap.secret_opc));
1239 if (opc_len != 16) {
1240 vty_out(vty, "%% need exactly 16 octets for oap-opc, got %d.%s",
1241 opc_len, VTY_NEWLINE);
1242 goto disable;
1243 }
1244
1245 g_cfg->oap.secret_opc_present = 1;
1246 return CMD_SUCCESS;
1247
1248disable:
1249 if (g_cfg->oap.client_id > 0) {
1250 vty_out(vty, "%% OAP client ID set, but invalid oap-opc value disables OAP.%s",
1251 VTY_NEWLINE);
1252 return CMD_WARNING;
1253 }
1254 return CMD_SUCCESS;
1255}
1256
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001257DEFUN(cfg_apn_name, cfg_apn_name_cmd,
1258 "access-point-name NAME",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001259 "Globally allow the given APN name for all subscribers.\n"
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001260 "Add this NAME to the list\n")
1261{
1262 return add_apn_ggsn_mapping(vty, argv[0], "", 0);
1263}
1264
1265DEFUN(cfg_no_apn_name, cfg_no_apn_name_cmd,
1266 "no access-point-name NAME",
1267 NO_STR "Configure a global list of allowed APNs\n"
1268 "Remove entry with NAME\n")
1269{
1270 struct apn_ctx *apn_ctx = sgsn_apn_ctx_by_name(argv[0], "");
1271 if (!apn_ctx)
1272 return CMD_SUCCESS;
1273
1274 sgsn_apn_ctx_free(apn_ctx);
1275 return CMD_SUCCESS;
1276}
1277
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001278DEFUN(cfg_cdr_filename, cfg_cdr_filename_cmd,
1279 "cdr filename NAME",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001280 "CDR\n"
1281 "Set the file name for the call-data-record file, logging the data usage of each subscriber.\n"
1282 "filename\n")
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001283{
1284 talloc_free(g_cfg->cdr.filename);
1285 g_cfg->cdr.filename = talloc_strdup(tall_vty_ctx, argv[0]);
1286 return CMD_SUCCESS;
1287}
1288
1289DEFUN(cfg_no_cdr_filename, cfg_no_cdr_filename_cmd,
1290 "no cdr filename",
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +01001291 NO_STR "CDR\nDisable saving CDR to file\n")
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001292{
1293 talloc_free(g_cfg->cdr.filename);
1294 g_cfg->cdr.filename = NULL;
1295 return CMD_SUCCESS;
1296}
1297
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +01001298DEFUN(cfg_cdr_trap, cfg_cdr_trap_cmd,
1299 "cdr trap",
1300 "CDR\nEnable sending CDR via TRAP CTRL messages\n")
1301{
1302 g_cfg->cdr.trap = true;
1303 return CMD_SUCCESS;
1304}
1305
1306DEFUN(cfg_no_cdr_trap, cfg_no_cdr_trap_cmd,
1307 "no cdr trap",
1308 NO_STR "CDR\nDisable sending CDR via TRAP CTRL messages\n")
1309{
1310 g_cfg->cdr.trap = false;
1311 return CMD_SUCCESS;
1312}
1313
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001314DEFUN(cfg_cdr_interval, cfg_cdr_interval_cmd,
1315 "cdr interval <1-2147483647>",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001316 "CDR\n"
1317 "Set the interval for the call-data-record file\n"
1318 "interval in seconds\n")
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001319{
1320 g_cfg->cdr.interval = atoi(argv[0]);
1321 return CMD_SUCCESS;
1322}
1323
Philippf1f34362016-08-26 17:00:21 +02001324#define COMPRESSION_STR "Configure compression\n"
1325DEFUN(cfg_no_comp_rfc1144, cfg_no_comp_rfc1144_cmd,
1326 "no compression rfc1144",
1327 NO_STR COMPRESSION_STR "disable rfc1144 TCP/IP header compression\n")
1328{
1329 g_cfg->pcomp_rfc1144.active = 0;
1330 g_cfg->pcomp_rfc1144.passive = 0;
1331 return CMD_SUCCESS;
1332}
1333
1334DEFUN(cfg_comp_rfc1144, cfg_comp_rfc1144_cmd,
1335 "compression rfc1144 active slots <1-256>",
1336 COMPRESSION_STR
Ruben Undheim55fcf112018-09-25 22:59:34 +02001337 "RFC1144 Header compression scheme\n"
Philippf1f34362016-08-26 17:00:21 +02001338 "Compression is actively proposed\n"
1339 "Number of compression state slots\n"
1340 "Number of compression state slots\n")
1341{
1342 g_cfg->pcomp_rfc1144.active = 1;
1343 g_cfg->pcomp_rfc1144.passive = 1;
1344 g_cfg->pcomp_rfc1144.s01 = atoi(argv[0]) - 1;
1345 return CMD_SUCCESS;
1346}
1347
1348DEFUN(cfg_comp_rfc1144p, cfg_comp_rfc1144p_cmd,
1349 "compression rfc1144 passive",
1350 COMPRESSION_STR
Ruben Undheim55fcf112018-09-25 22:59:34 +02001351 "RFC1144 Header compression scheme\n"
Philippf1f34362016-08-26 17:00:21 +02001352 "Compression is available on request\n")
1353{
1354 g_cfg->pcomp_rfc1144.active = 0;
1355 g_cfg->pcomp_rfc1144.passive = 1;
1356 return CMD_SUCCESS;
1357}
1358
Philipp73f83d52016-09-02 13:38:01 +02001359DEFUN(cfg_no_comp_v42bis, cfg_no_comp_v42bis_cmd,
1360 "no compression v42bis",
1361 NO_STR COMPRESSION_STR "disable V.42bis data compression\n")
1362{
1363 g_cfg->dcomp_v42bis.active = 0;
1364 g_cfg->dcomp_v42bis.passive = 0;
1365 return CMD_SUCCESS;
1366}
1367
1368DEFUN(cfg_comp_v42bis, cfg_comp_v42bis_cmd,
1369 "compression v42bis active direction (ms|sgsn|both) codewords <512-65535> strlen <6-250>",
1370 COMPRESSION_STR
Ruben Undheim55fcf112018-09-25 22:59:34 +02001371 "V.42bis data compression scheme\n"
Philipp73f83d52016-09-02 13:38:01 +02001372 "Compression is actively proposed\n"
1373 "Direction in which the compression shall be active (p0)\n"
1374 "Compress ms->sgsn direction only\n"
1375 "Compress sgsn->ms direction only\n"
1376 "Both directions\n"
1377 "Number of codewords (p1)\n"
1378 "Number of codewords\n"
1379 "Maximum string length (p2)\n" "Maximum string length\n")
1380{
1381 g_cfg->dcomp_v42bis.active = 1;
1382 g_cfg->dcomp_v42bis.passive = 1;
1383
1384 switch (argv[0][0]) {
1385 case 'm':
1386 g_cfg->dcomp_v42bis.p0 = 1;
1387 break;
1388 case 's':
1389 g_cfg->dcomp_v42bis.p0 = 2;
1390 break;
1391 case 'b':
1392 g_cfg->dcomp_v42bis.p0 = 3;
1393 break;
1394 }
1395
1396 g_cfg->dcomp_v42bis.p1 = atoi(argv[1]);
1397 g_cfg->dcomp_v42bis.p2 = atoi(argv[2]);
1398 return CMD_SUCCESS;
1399}
1400
1401DEFUN(cfg_comp_v42bisp, cfg_comp_v42bisp_cmd,
1402 "compression v42bis passive",
1403 COMPRESSION_STR
Ruben Undheim55fcf112018-09-25 22:59:34 +02001404 "V.42bis data compression scheme\n"
Philipp73f83d52016-09-02 13:38:01 +02001405 "Compression is available on request\n")
1406{
1407 g_cfg->dcomp_v42bis.active = 0;
1408 g_cfg->dcomp_v42bis.passive = 1;
1409 return CMD_SUCCESS;
1410}
1411
Pau Espin Pedrol2c908992019-08-19 19:06:06 +02001412#if BUILD_IU
1413DEFUN(cfg_sgsn_cs7_instance_iu,
1414 cfg_sgsn_cs7_instance_iu_cmd,
1415 "cs7-instance-iu <0-15>",
1416 "Set SS7 to be used by the Iu-Interface.\n" "SS7 instance reference number (default: 0)\n")
1417{
1418 g_cfg->iu.cs7_instance = atoi(argv[0]);
1419 return CMD_SUCCESS;
1420}
1421#endif
1422
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001423int sgsn_vty_init(struct sgsn_config *cfg)
Harald Welte288be162010-05-01 16:48:27 +02001424{
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001425 g_cfg = cfg;
1426
Pau Espin Pedrola299d652019-08-14 19:11:10 +02001427 g_cfg->T_defs = sgsn_T_defs;
1428 osmo_tdefs_reset(g_cfg->T_defs);
1429
Harald Welted193cb32010-05-17 22:58:03 +02001430 install_element_ve(&show_sgsn_cmd);
1431 //install_element_ve(&show_mmctx_tlli_cmd);
1432 install_element_ve(&show_mmctx_imsi_cmd);
1433 install_element_ve(&show_mmctx_all_cmd);
1434 install_element_ve(&show_pdpctx_all_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001435 install_element_ve(&show_subscr_cache_cmd);
Pau Espin Pedrola299d652019-08-14 19:11:10 +02001436 install_element_ve(&show_timer_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001437
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01001438 install_element(ENABLE_NODE, &update_subscr_insert_auth_triplet_cmd);
Jacob Erlbeckd9193432015-01-19 14:11:46 +01001439 install_element(ENABLE_NODE, &update_subscr_create_cmd);
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001440 install_element(ENABLE_NODE, &update_subscr_destroy_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001441 install_element(ENABLE_NODE, &update_subscr_cancel_cmd);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001442 install_element(ENABLE_NODE, &update_subscr_update_location_result_cmd);
1443 install_element(ENABLE_NODE, &update_subscr_update_auth_info_cmd);
Alexander Couzensc503f0a2018-08-07 17:50:04 +02001444 install_element(ENABLE_NODE, &reset_sgsn_state_cmd);
Harald Welte288be162010-05-01 16:48:27 +02001445
1446 install_element(CONFIG_NODE, &cfg_sgsn_cmd);
1447 install_node(&sgsn_node, config_write_sgsn);
Keithc70e8382020-10-19 22:24:48 +02001448 install_element(SGSN_NODE, &cfg_sgsn_state_dir_cmd);
Harald Weltee300d002010-06-02 12:41:34 +02001449 install_element(SGSN_NODE, &cfg_sgsn_bind_addr_cmd);
Harald Welted193cb32010-05-17 22:58:03 +02001450 install_element(SGSN_NODE, &cfg_ggsn_remote_ip_cmd);
1451 //install_element(SGSN_NODE, &cfg_ggsn_remote_port_cmd);
1452 install_element(SGSN_NODE, &cfg_ggsn_gtp_version_cmd);
Pau Espin Pedrolfa120102018-07-09 20:37:47 +02001453 install_element(SGSN_NODE, &cfg_ggsn_echo_interval_cmd);
Pau Espin Pedrola83850c2018-07-10 12:43:59 +02001454 install_element(SGSN_NODE, &cfg_ggsn_no_echo_interval_cmd);
Harald Welte7f6da482013-03-19 11:00:13 +01001455 install_element(SGSN_NODE, &cfg_imsi_acl_cmd);
Harald Welte3dfb5492013-03-19 11:48:54 +01001456 install_element(SGSN_NODE, &cfg_auth_policy_cmd);
Vadim Yanitskiy794f4462019-05-27 05:39:06 +07001457 install_element(SGSN_NODE, &cfg_authentication_cmd);
Max93408ae2016-06-28 14:10:16 +02001458 install_element(SGSN_NODE, &cfg_encrypt_cmd);
Stefan Sperling88220092018-12-11 14:42:00 +01001459 install_element(SGSN_NODE, &cfg_gsup_ipa_name_cmd);
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001460 install_element(SGSN_NODE, &cfg_gsup_remote_ip_cmd);
1461 install_element(SGSN_NODE, &cfg_gsup_remote_port_cmd);
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001462 install_element(SGSN_NODE, &cfg_gsup_oap_id_cmd);
1463 install_element(SGSN_NODE, &cfg_gsup_oap_k_cmd);
1464 install_element(SGSN_NODE, &cfg_gsup_oap_opc_cmd);
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +01001465 install_element(SGSN_NODE, &cfg_apn_ggsn_cmd);
1466 install_element(SGSN_NODE, &cfg_apn_imsi_ggsn_cmd);
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001467 install_element(SGSN_NODE, &cfg_apn_name_cmd);
1468 install_element(SGSN_NODE, &cfg_no_apn_name_cmd);
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001469 install_element(SGSN_NODE, &cfg_cdr_filename_cmd);
1470 install_element(SGSN_NODE, &cfg_no_cdr_filename_cmd);
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +01001471 install_element(SGSN_NODE, &cfg_cdr_trap_cmd);
1472 install_element(SGSN_NODE, &cfg_no_cdr_trap_cmd);
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001473 install_element(SGSN_NODE, &cfg_cdr_interval_cmd);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001474 install_element(SGSN_NODE, &cfg_ggsn_dynamic_lookup_cmd);
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +08001475 install_element(SGSN_NODE, &cfg_grx_ggsn_cmd);
Harald Welte288be162010-05-01 16:48:27 +02001476
Pau Espin Pedrola299d652019-08-14 19:11:10 +02001477 install_element(SGSN_NODE, &cfg_sgsn_timer_cmd);
Harald Welte94508822015-08-15 19:08:21 +02001478
Philippf1f34362016-08-26 17:00:21 +02001479 install_element(SGSN_NODE, &cfg_no_comp_rfc1144_cmd);
1480 install_element(SGSN_NODE, &cfg_comp_rfc1144_cmd);
1481 install_element(SGSN_NODE, &cfg_comp_rfc1144p_cmd);
Philipp73f83d52016-09-02 13:38:01 +02001482 install_element(SGSN_NODE, &cfg_no_comp_v42bis_cmd);
1483 install_element(SGSN_NODE, &cfg_comp_v42bis_cmd);
1484 install_element(SGSN_NODE, &cfg_comp_v42bisp_cmd);
Neels Hofmeyr2188a772016-05-20 21:59:55 +02001485
1486#ifdef BUILD_IU
Pau Espin Pedrol2c908992019-08-19 19:06:06 +02001487 install_element(SGSN_NODE, &cfg_sgsn_cs7_instance_iu_cmd);
Neels Hofmeyra7a39472017-07-05 15:19:52 +02001488 ranap_iu_vty_init(SGSN_NODE, &g_cfg->iu.rab_assign_addr_enc);
Neels Hofmeyr2188a772016-05-20 21:59:55 +02001489#endif
Harald Welte288be162010-05-01 16:48:27 +02001490 return 0;
1491}
1492
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001493int sgsn_parse_config(const char *config_file)
Harald Welte288be162010-05-01 16:48:27 +02001494{
1495 int rc;
1496
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001497 /* make sure sgsn_vty_init() was called before this */
1498 OSMO_ASSERT(g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +01001499
Harald Weltedcccb182010-05-16 20:52:23 +02001500 rc = vty_read_config_file(config_file, NULL);
Harald Welte288be162010-05-01 16:48:27 +02001501 if (rc < 0) {
1502 fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
1503 return rc;
1504 }
1505
Neels Hofmeyr27355c92017-02-24 06:28:31 +01001506 if (g_cfg->auth_policy == SGSN_AUTH_POLICY_REMOTE
1507 && !(g_cfg->gsup_server_addr.sin_addr.s_addr
1508 && g_cfg->gsup_server_port)) {
1509 fprintf(stderr, "Configuration error:"
1510 " 'auth-policy remote' requires both"
1511 " 'gsup remote-ip' and 'gsup remote-port'\n");
1512 return -EINVAL;
1513 }
1514
Harald Welte288be162010-05-01 16:48:27 +02001515 return 0;
1516}