blob: 9200822e392c6e978754cf3e695039843eaa30dc [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
Pau Espin Pedrola299d652019-08-14 19:11:10 +020093
94static struct osmo_tdef sgsn_T_defs[] = {
95 { .T=3312, .default_val=GSM0408_T3312_SECS, .desc="Periodic RA Update timer (s)" },
96 { .T=3313, .default_val=GSM0408_T3313_SECS, .desc="Waiting for paging response timer (s)" },
Alexander Couzens39cbecd2017-02-03 22:16:05 +010097 { .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 +020098 { .T=3316, .default_val=GSM0408_T3316_SECS, .desc="AA-Ready timer (s)" },
99 { .T=3322, .default_val=GSM0408_T3322_SECS, .desc="Detach request -> accept timer (s)" },
100 { .T=3350, .default_val=GSM0408_T3350_SECS, .desc="Waiting for ATT/RAU/TMSI_COMPL timer (s)" },
101 { .T=3360, .default_val=GSM0408_T3360_SECS, .desc="Waiting for AUTH/CIPH response timer (s)" },
102 { .T=3370, .default_val=GSM0408_T3370_SECS, .desc="Waiting for IDENTITY response timer (s)" },
103 { .T=3385, .default_val=GSM0408_T3385_SECS, .desc="Wait for ACT PDP CTX REQ timer (s)" },
104 { .T=3386, .default_val=GSM0408_T3386_SECS, .desc="Wait for MODIFY PDP CTX ACK timer (s)" },
105 { .T=3395, .default_val=GSM0408_T3395_SECS, .desc="Wait for DEACT PDP CTX ACK timer (s)" },
106 { .T=3397, .default_val=GSM0408_T3397_SECS, .desc="Wait for DEACT AA PDP CTX ACK timer (s)" },
107 {}
108};
109
110DEFUN(show_timer, show_timer_cmd,
111 "show timer " OSMO_TDEF_VTY_ARG_T_OPTIONAL,
112 SHOW_STR "Show timers\n"
113 OSMO_TDEF_VTY_DOC_T)
114{
115 const char *T_arg = argc > 0 ? argv[0] : NULL;
116 return osmo_tdef_vty_show_cmd(vty, g_cfg->T_defs, T_arg, NULL);
Harald Welte94508822015-08-15 19:08:21 +0200117}
118
Pau Espin Pedrola299d652019-08-14 19:11:10 +0200119DEFUN(cfg_sgsn_timer, cfg_sgsn_timer_cmd,
120 "timer " OSMO_TDEF_VTY_ARG_SET_OPTIONAL,
121 "Configure or show timers\n"
122 OSMO_TDEF_VTY_DOC_SET)
123{
124 /* If any arguments are missing, redirect to 'show' */
125 if (argc < 2)
126 return show_timer(self, vty, argc, argv);
127 return osmo_tdef_vty_set_cmd(vty, g_cfg->T_defs, argv);
128}
Harald Welte94508822015-08-15 19:08:21 +0200129
Holger Hans Peter Freythera2730302014-03-23 18:08:26 +0100130char *gprs_pdpaddr2str(uint8_t *pdpa, uint8_t len)
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200131{
132 static char str[INET6_ADDRSTRLEN + 10];
133
134 if (!pdpa || len < 2)
135 return "none";
136
137 switch (pdpa[0] & 0x0f) {
138 case PDP_TYPE_ORG_IETF:
139 switch (pdpa[1]) {
140 case PDP_TYPE_N_IETF_IPv4:
141 if (len < 2 + 4)
142 break;
143 strcpy(str, "IPv4 ");
144 inet_ntop(AF_INET, pdpa+2, str+5, sizeof(str)-5);
145 return str;
146 case PDP_TYPE_N_IETF_IPv6:
147 if (len < 2 + 8)
148 break;
149 strcpy(str, "IPv6 ");
150 inet_ntop(AF_INET6, pdpa+2, str+5, sizeof(str)-5);
151 return str;
152 default:
153 break;
154 }
155 break;
156 case PDP_TYPE_ORG_ETSI:
157 if (pdpa[1] == PDP_TYPE_N_ETSI_PPP)
158 return "PPP";
159 break;
160 default:
161 break;
162 }
163
164 return "invalid";
165}
166
Harald Welte288be162010-05-01 16:48:27 +0200167static struct cmd_node sgsn_node = {
168 SGSN_NODE,
Harald Welte570ce242012-08-17 13:16:10 +0200169 "%s(config-sgsn)# ",
Harald Welte288be162010-05-01 16:48:27 +0200170 1,
171};
172
173static int config_write_sgsn(struct vty *vty)
174{
Harald Welte77289c22010-05-18 14:32:29 +0200175 struct sgsn_ggsn_ctx *gctx;
Harald Welte7f6da482013-03-19 11:00:13 +0100176 struct imsi_acl_entry *acl;
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100177 struct apn_ctx *actx;
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800178 struct ares_addr_node *server;
Harald Welte288be162010-05-01 16:48:27 +0200179
180 vty_out(vty, "sgsn%s", VTY_NEWLINE);
181
Harald Weltee300d002010-06-02 12:41:34 +0200182 vty_out(vty, " gtp local-ip %s%s",
183 inet_ntoa(g_cfg->gtp_listenaddr.sin_addr), VTY_NEWLINE);
184
Harald Welted193cb32010-05-17 22:58:03 +0200185 llist_for_each_entry(gctx, &sgsn_ggsn_ctxts, list) {
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800186 if (gctx->id == UINT32_MAX)
187 continue;
188
Harald Welteff3bde82010-05-19 15:09:09 +0200189 vty_out(vty, " ggsn %u remote-ip %s%s", gctx->id,
Harald Welted193cb32010-05-17 22:58:03 +0200190 inet_ntoa(gctx->remote_addr), VTY_NEWLINE);
Harald Welteff3bde82010-05-19 15:09:09 +0200191 vty_out(vty, " ggsn %u gtp-version %u%s", gctx->id,
Harald Welted193cb32010-05-17 22:58:03 +0200192 gctx->gtp_version, VTY_NEWLINE);
Pau Espin Pedrolaa89f5d2019-08-28 16:08:45 +0200193 if (gctx->echo_interval)
194 vty_out(vty, " ggsn %u echo-interval %u%s",
Pau Espin Pedrolfa120102018-07-09 20:37:47 +0200195 gctx->id, gctx->echo_interval, VTY_NEWLINE);
Pau Espin Pedrola83850c2018-07-10 12:43:59 +0200196 else
197 vty_out(vty, " ggsn %u no echo-interval%s",
198 gctx->id, VTY_NEWLINE);
Harald Welte288be162010-05-01 16:48:27 +0200199 }
200
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800201 if (sgsn->cfg.dynamic_lookup)
202 vty_out(vty, " ggsn dynamic%s", VTY_NEWLINE);
203
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800204 for (server = sgsn->ares_servers; server; server = server->next)
205 vty_out(vty, " grx-dns-add %s%s", inet_ntoa(server->addr.addr4), VTY_NEWLINE);
206
Max93408ae2016-06-28 14:10:16 +0200207 if (g_cfg->cipher != GPRS_ALGO_GEA0)
208 vty_out(vty, " encryption %s%s",
209 get_value_string(gprs_cipher_names, g_cfg->cipher),
210 VTY_NEWLINE);
Stefan Sperling88220092018-12-11 14:42:00 +0100211 if (g_cfg->sgsn_ipa_name)
212 vty_out(vty, " gsup ipa-name %s%s", g_cfg->sgsn_ipa_name, VTY_NEWLINE);
Jacob Erlbeck39f040d2014-12-18 12:46:47 +0100213 if (g_cfg->gsup_server_addr.sin_addr.s_addr)
214 vty_out(vty, " gsup remote-ip %s%s",
215 inet_ntoa(g_cfg->gsup_server_addr.sin_addr), VTY_NEWLINE);
216 if (g_cfg->gsup_server_port)
217 vty_out(vty, " gsup remote-port %d%s",
218 g_cfg->gsup_server_port, VTY_NEWLINE);
Pau Espin Pedrold1463bc2019-06-13 19:03:25 +0200219 if (g_cfg->auth_policy == SGSN_AUTH_POLICY_REMOTE && !g_cfg->require_authentication)
220 vty_out(vty, " authentication optional%s", VTY_NEWLINE);
Max176b62a2016-07-04 11:09:07 +0200221 vty_out(vty, " auth-policy %s%s",
222 get_value_string(sgsn_auth_pol_strs, g_cfg->auth_policy),
223 VTY_NEWLINE);
Neels Hofmeyr568a7272015-10-12 11:57:38 +0200224
225 vty_out(vty, " gsup oap-id %d%s",
226 (int)g_cfg->oap.client_id, VTY_NEWLINE);
227 if (g_cfg->oap.secret_k_present != 0)
228 vty_out(vty, " gsup oap-k %s%s",
229 osmo_hexdump_nospc(g_cfg->oap.secret_k, sizeof(g_cfg->oap.secret_k)),
230 VTY_NEWLINE);
231 if (g_cfg->oap.secret_opc_present != 0)
232 vty_out(vty, " gsup oap-opc %s%s",
233 osmo_hexdump_nospc(g_cfg->oap.secret_opc, sizeof(g_cfg->oap.secret_opc)),
234 VTY_NEWLINE);
235
Harald Welte7f6da482013-03-19 11:00:13 +0100236 llist_for_each_entry(acl, &g_cfg->imsi_acl, list)
237 vty_out(vty, " imsi-acl add %s%s", acl->imsi, VTY_NEWLINE);
238
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100239 if (llist_empty(&sgsn_apn_ctxts))
240 vty_out(vty, " ! apn * ggsn 0%s", VTY_NEWLINE);
241 llist_for_each_entry(actx, &sgsn_apn_ctxts, list) {
242 if (strlen(actx->imsi_prefix) > 0)
Holger Hans Peter Freytherb7ae0b32015-05-29 15:11:55 +0200243 vty_out(vty, " apn %s imsi-prefix %s ggsn %u%s",
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100244 actx->name, actx->imsi_prefix, actx->ggsn->id,
245 VTY_NEWLINE);
246 else
Holger Hans Peter Freytherb7ae0b32015-05-29 15:11:55 +0200247 vty_out(vty, " apn %s ggsn %u%s", actx->name,
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100248 actx->ggsn->id, VTY_NEWLINE);
249 }
250
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +0200251 if (g_cfg->cdr.filename)
252 vty_out(vty, " cdr filename %s%s", g_cfg->cdr.filename, VTY_NEWLINE);
253 else
254 vty_out(vty, " no cdr filename%s", VTY_NEWLINE);
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +0100255 if (g_cfg->cdr.trap)
256 vty_out(vty, " cdr trap%s", VTY_NEWLINE);
257 else
258 vty_out(vty, " no cdr trap%s", VTY_NEWLINE);
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +0200259 vty_out(vty, " cdr interval %d%s", g_cfg->cdr.interval, VTY_NEWLINE);
260
Pau Espin Pedrola299d652019-08-14 19:11:10 +0200261 osmo_tdef_vty_write(vty, g_cfg->T_defs, " timer ");
Harald Welte94508822015-08-15 19:08:21 +0200262
Philippf1f34362016-08-26 17:00:21 +0200263 if (g_cfg->pcomp_rfc1144.active) {
264 vty_out(vty, " compression rfc1144 active slots %d%s",
265 g_cfg->pcomp_rfc1144.s01 + 1, VTY_NEWLINE);
266 } else if (g_cfg->pcomp_rfc1144.passive) {
267 vty_out(vty, " compression rfc1144 passive%s", VTY_NEWLINE);
268 } else
269 vty_out(vty, " no compression rfc1144%s", VTY_NEWLINE);
270
Philipp73f83d52016-09-02 13:38:01 +0200271 if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 1) {
272 vty_out(vty,
273 " compression v42bis active direction sgsn codewords %d strlen %d%s",
274 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
275 VTY_NEWLINE);
276 } else if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 2) {
277 vty_out(vty,
278 " compression v42bis active direction ms codewords %d strlen %d%s",
279 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
280 VTY_NEWLINE);
281 } else if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 3) {
282 vty_out(vty,
283 " compression v42bis active direction both codewords %d strlen %d%s",
284 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
285 VTY_NEWLINE);
286 } else if (g_cfg->dcomp_v42bis.passive) {
287 vty_out(vty, " compression v42bis passive%s", VTY_NEWLINE);
288 } else
289 vty_out(vty, " no compression v42bis%s", VTY_NEWLINE);
290
Neels Hofmeyr2188a772016-05-20 21:59:55 +0200291#ifdef BUILD_IU
Pau Espin Pedrol2c908992019-08-19 19:06:06 +0200292 vty_out(vty, " cs7-instance-iu %u%s", g_cfg->iu.cs7_instance,
293 VTY_NEWLINE);
Neels Hofmeyra7a39472017-07-05 15:19:52 +0200294 ranap_iu_vty_config_write(vty, " ");
Neels Hofmeyr2188a772016-05-20 21:59:55 +0200295#endif
296
Harald Welte288be162010-05-01 16:48:27 +0200297 return CMD_SUCCESS;
298}
299
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100300#define SGSN_STR "Configure the SGSN\n"
301#define GGSN_STR "Configure the GGSN information\n"
Harald Weltee300d002010-06-02 12:41:34 +0200302
303DEFUN(cfg_sgsn, cfg_sgsn_cmd,
304 "sgsn",
305 SGSN_STR)
Harald Welte288be162010-05-01 16:48:27 +0200306{
307 vty->node = SGSN_NODE;
308 return CMD_SUCCESS;
309}
310
Harald Weltee300d002010-06-02 12:41:34 +0200311DEFUN(cfg_sgsn_bind_addr, cfg_sgsn_bind_addr_cmd,
312 "gtp local-ip A.B.C.D",
313 "GTP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100314 "Set the IP address for the local GTP bind for the Gp interface (towards the GGSNs)."
315 " Note: in case you would like to run the GGSN on the same machine as the SGSN, you can not run"
316 " both on the same IP address, since both sides are specified to use the same GTP port numbers"
317 " (" OSMO_STRINGIFY_VAL(GTP1C_PORT) " and " OSMO_STRINGIFY_VAL(GTP1U_PORT) ")."
318 " For example, you could use 127.0.0.1 for the SGSN and 127.0.0.2 for the GGSN in such"
319 " situations.\n"
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100320 "IPv4 Address\n")
Harald Weltee300d002010-06-02 12:41:34 +0200321{
322 inet_aton(argv[0], &g_cfg->gtp_listenaddr.sin_addr);
323
324 return CMD_SUCCESS;
325}
326
Harald Welted193cb32010-05-17 22:58:03 +0200327DEFUN(cfg_ggsn_remote_ip, cfg_ggsn_remote_ip_cmd,
328 "ggsn <0-255> remote-ip A.B.C.D",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100329 GGSN_STR "GGSN Number\n"
330 "Configure this static GGSN to use the specified remote IP address.\n"
331 "IPv4 Address\n")
Harald Welted193cb32010-05-17 22:58:03 +0200332{
333 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200334 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welte288be162010-05-01 16:48:27 +0200335
Harald Welted193cb32010-05-17 22:58:03 +0200336 inet_aton(argv[1], &ggc->remote_addr);
Harald Welte288be162010-05-01 16:48:27 +0200337
Harald Welted193cb32010-05-17 22:58:03 +0200338 return CMD_SUCCESS;
339}
340
341#if 0
342DEFUN(cfg_ggsn_remote_port, cfg_ggsn_remote_port_cmd,
343 "ggsn <0-255> remote-port <0-65535>",
344 "")
345{
346 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200347 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welted193cb32010-05-17 22:58:03 +0200348 uint16_t port = atoi(argv[1]);
349
350}
351#endif
352
353DEFUN(cfg_ggsn_gtp_version, cfg_ggsn_gtp_version_cmd,
354 "ggsn <0-255> gtp-version (0|1)",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100355 GGSN_STR "GGSN Number\n" "GTP Version\n"
356 "Version 0\n" "Version 1\n")
Harald Welted193cb32010-05-17 22:58:03 +0200357{
358 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200359 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welted193cb32010-05-17 22:58:03 +0200360
361 if (atoi(argv[1]))
362 ggc->gtp_version = 1;
363 else
364 ggc->gtp_version = 0;
365
366 return CMD_SUCCESS;
367}
368
Pau Espin Pedrolfa120102018-07-09 20:37:47 +0200369/* Seee 3GPP TS 29.060 section 7.2.1 */
370DEFUN(cfg_ggsn_echo_interval, cfg_ggsn_echo_interval_cmd,
371 "ggsn <0-255> echo-interval <1-36000>",
372 GGSN_STR "GGSN Number\n"
373 "Send an echo request to this static GGSN every interval.\n"
374 "Interval between echo requests in seconds.\n")
375{
376 uint32_t id = atoi(argv[0]);
377 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
378
379 ggc->echo_interval = atoi(argv[1]);
380
381 if (ggc->echo_interval < 60)
Pau Espin Pedrolba2e5002019-05-27 17:35:32 +0200382 vty_out(vty, "%% 3GPP TS 29.060 section 7.2.1 states interval should " \
Pau Espin Pedrolfa120102018-07-09 20:37:47 +0200383 "not be lower than 60 seconds, use this value for " \
384 "testing purposes only!%s", VTY_NEWLINE);
385
Alexander Couzens176a4d22018-09-18 20:07:37 +0200386 sgsn_ggsn_ctx_check_echo_timer(ggc);
Pau Espin Pedrolfa120102018-07-09 20:37:47 +0200387 return CMD_SUCCESS;
388}
389
Pau Espin Pedrola83850c2018-07-10 12:43:59 +0200390DEFUN(cfg_ggsn_no_echo_interval, cfg_ggsn_no_echo_interval_cmd,
391 "ggsn <0-255> no echo-interval",
392 GGSN_STR "GGSN Number\n"
393 NO_STR "Send an echo request to this static GGSN every interval.\n")
394{
395 uint32_t id = atoi(argv[0]);
396 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
397
Pau Espin Pedrolaa89f5d2019-08-28 16:08:45 +0200398 ggc->echo_interval = 0;
Alexander Couzens176a4d22018-09-18 20:07:37 +0200399 sgsn_ggsn_ctx_check_echo_timer(ggc);
Pau Espin Pedrola83850c2018-07-10 12:43:59 +0200400
401 return CMD_SUCCESS;
402}
403
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800404DEFUN(cfg_ggsn_dynamic_lookup, cfg_ggsn_dynamic_lookup_cmd,
405 "ggsn dynamic",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100406 GGSN_STR
407 "Enable dynamic resolving of GGSNs based on DNS resolving the APN name like in a GRX-style setup."
408 " Changing this setting requires a restart.\n")
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800409{
410 sgsn->cfg.dynamic_lookup = 1;
411 return CMD_SUCCESS;
412}
413
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800414DEFUN(cfg_grx_ggsn, cfg_grx_ggsn_cmd,
415 "grx-dns-add A.B.C.D",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100416 "Use the specified IP address for DNS-resolving the AP names to GGSN IP addresses\n"
417 "IPv4 address\n")
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800418{
Pau Espin Pedrolb1d1c242018-10-30 17:27:59 +0100419 struct ares_addr_node *node = talloc_zero(tall_sgsn_ctx, struct ares_addr_node);
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800420 node->family = AF_INET;
421 inet_aton(argv[0], &node->addr.addr4);
422
423 node->next = sgsn->ares_servers;
424 sgsn->ares_servers = node;
425 return CMD_SUCCESS;
426}
427
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100428#define APN_STR "Configure the information per APN\n"
429#define APN_GW_STR "The APN gateway name optionally prefixed by '*' (wildcard)\n"
430
431static int add_apn_ggsn_mapping(struct vty *vty, const char *apn_str,
432 const char *imsi_prefix, int ggsn_id)
433{
434 struct apn_ctx *actx;
435 struct sgsn_ggsn_ctx *ggsn;
436
437 ggsn = sgsn_ggsn_ctx_by_id(ggsn_id);
438 if (ggsn == NULL) {
439 vty_out(vty, "%% a GGSN with id %d has not been defined%s",
440 ggsn_id, VTY_NEWLINE);
441 return CMD_WARNING;
442 }
443
444 actx = sgsn_apn_ctx_find_alloc(apn_str, imsi_prefix);
445 if (!actx) {
446 vty_out(vty, "%% unable to create APN context for %s/%s%s",
447 apn_str, imsi_prefix, VTY_NEWLINE);
448 return CMD_WARNING;
449 }
450
451 actx->ggsn = ggsn;
452
453 return CMD_SUCCESS;
454}
455
Harald Welted193cb32010-05-17 22:58:03 +0200456DEFUN(cfg_apn_ggsn, cfg_apn_ggsn_cmd,
457 "apn APNAME ggsn <0-255>",
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100458 APN_STR APN_GW_STR
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100459 "Select the GGSN to use for the given APN gateway prefix\n"
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100460 "The GGSN id")
Harald Welted193cb32010-05-17 22:58:03 +0200461{
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100462
463 return add_apn_ggsn_mapping(vty, argv[0], "", atoi(argv[1]));
Harald Welted193cb32010-05-17 22:58:03 +0200464}
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100465
466DEFUN(cfg_apn_imsi_ggsn, cfg_apn_imsi_ggsn_cmd,
467 "apn APNAME imsi-prefix IMSIPRE ggsn <0-255>",
468 APN_STR APN_GW_STR
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100469 "Select the GGSN to use for the given APN gateway prefix if and only if the IMSI matches the"
470 " given prefix.\n"
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100471 "An IMSI prefix\n"
472 "Select the GGSN to use when APN gateway and IMSI prefix match\n"
473 "The GGSN id")
474{
475
476 return add_apn_ggsn_mapping(vty, argv[0], argv[1], atoi(argv[2]));
477}
Harald Welted193cb32010-05-17 22:58:03 +0200478
Maxc005db72017-10-27 18:43:29 +0200479char *sgsn_gtp_ntoa(struct ul16_t *ul)
Harald Welte471ac7d2016-12-15 19:48:58 +0100480{
Max8492c202017-12-05 17:28:15 +0100481 struct in_addr ia;
482
483 if (gsna2in_addr(&ia, ul) != 0)
Harald Welte471ac7d2016-12-15 19:48:58 +0100484 return "UNKNOWN";
Max8492c202017-12-05 17:28:15 +0100485
486 return inet_ntoa(ia);
Harald Welte471ac7d2016-12-15 19:48:58 +0100487}
488
Harald Welted193cb32010-05-17 22:58:03 +0200489static void vty_dump_pdp(struct vty *vty, const char *pfx,
490 struct sgsn_pdp_ctx *pdp)
491{
Jacob Erlbeck99985b52014-10-13 10:32:00 +0200492 const char *imsi = pdp->mm ? pdp->mm->imsi : "(detaching)";
Harald Welte471ac7d2016-12-15 19:48:58 +0100493 vty_out(vty, "%sPDP Context IMSI: %s, SAPI: %u, NSAPI: %u, TI: %u%s",
494 pfx, imsi, pdp->sapi, pdp->nsapi, pdp->ti, VTY_NEWLINE);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200495 if (pdp->lib) {
Max7933d962017-10-19 16:52:30 +0200496 char apnbuf[APN_MAXLEN + 1];
Harald Weltedfbd2c82017-08-13 00:56:45 +0200497 vty_out(vty, "%s APN: %s%s", pfx,
Max7933d962017-10-19 16:52:30 +0200498 osmo_apn_to_str(apnbuf, pdp->lib->apn_use.v, pdp->lib->apn_use.l),
Harald Weltedfbd2c82017-08-13 00:56:45 +0200499 VTY_NEWLINE);
500 vty_out(vty, "%s PDP Address: %s%s", pfx,
501 gprs_pdpaddr2str(pdp->lib->eua.v, pdp->lib->eua.l),
502 VTY_NEWLINE);
Maxb24af2b2017-12-05 17:54:42 +0100503 vty_out(vty, "%s GTPv%d Local Control(%s / TEIC: 0x%08x) ", pfx, pdp->lib->version,
Maxc005db72017-10-27 18:43:29 +0200504 sgsn_gtp_ntoa(&pdp->lib->gsnlc), pdp->lib->teic_own);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200505 vty_out(vty, "Data(%s / TEID: 0x%08x)%s",
Maxc005db72017-10-27 18:43:29 +0200506 sgsn_gtp_ntoa(&pdp->lib->gsnlu), pdp->lib->teid_own, VTY_NEWLINE);
Maxb24af2b2017-12-05 17:54:42 +0100507 vty_out(vty, "%s GTPv%d Remote Control(%s / TEIC: 0x%08x) ", pfx, pdp->lib->version,
Maxc005db72017-10-27 18:43:29 +0200508 sgsn_gtp_ntoa(&pdp->lib->gsnrc), pdp->lib->teic_gn);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200509 vty_out(vty, "Data(%s / TEID: 0x%08x)%s",
Maxc005db72017-10-27 18:43:29 +0200510 sgsn_gtp_ntoa(&pdp->lib->gsnru), pdp->lib->teid_gn, VTY_NEWLINE);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200511 }
Harald Welte471ac7d2016-12-15 19:48:58 +0100512
Harald Welteefbdee92010-06-10 00:20:12 +0200513 vty_out_rate_ctr_group(vty, " ", pdp->ctrg);
Harald Welted193cb32010-05-17 22:58:03 +0200514}
515
516static void vty_dump_mmctx(struct vty *vty, const char *pfx,
517 struct sgsn_mm_ctx *mm, int pdp)
518{
Pau Espin Pedrol9119d502019-08-30 17:48:10 +0200519 uint32_t id = 0;
Pau Espin Pedrolfd815bb2019-08-30 18:32:42 +0200520 const char *mm_state_name = NULL;
Pau Espin Pedrol9119d502019-08-30 17:48:10 +0200521
522 switch(mm->ran_type) {
523 case MM_CTX_T_UTRAN_Iu:
524#if BUILD_IU
525 id = mm->iu.ue_ctx->conn_id;
Pau Espin Pedrolfd815bb2019-08-30 18:32:42 +0200526 mm_state_name = osmo_fsm_inst_state_name(mm->iu.mm_state_fsm);
Pau Espin Pedrol9119d502019-08-30 17:48:10 +0200527#endif
528 break;
529 case MM_CTX_T_GERAN_Gb:
530 id = mm->gb.tlli;
Pau Espin Pedrolfd815bb2019-08-30 18:32:42 +0200531 mm_state_name = osmo_fsm_inst_state_name(mm->gb.mm_state_fsm);
Pau Espin Pedrol9119d502019-08-30 17:48:10 +0200532 break;
533 }
534
Harald Welted193cb32010-05-17 22:58:03 +0200535 vty_out(vty, "%sMM Context for IMSI %s, IMEI %s, P-TMSI %08x%s",
536 pfx, mm->imsi, mm->imei, mm->p_tmsi, VTY_NEWLINE);
Holger Hans Peter Freyther8ee13e22015-05-18 10:00:03 +0200537 vty_out(vty, "%s MSISDN: %s, TLLI: %08x%s HLR: %s",
Pau Espin Pedrol9119d502019-08-30 17:48:10 +0200538 pfx, mm->msisdn, id, mm->hlr, VTY_NEWLINE);
Pau Espin Pedrolfd815bb2019-08-30 18:32:42 +0200539 vty_out(vty, "%s GMM State: %s, Routeing Area: %s, Cell ID: %u%s",
Pau Espin Pedrol31c46572019-09-02 16:45:27 +0200540 pfx, osmo_fsm_inst_state_name(mm->gmm_fsm),
Neels Hofmeyr10719b72018-02-21 00:39:36 +0100541 osmo_rai_name(&mm->ra), mm->gb.cell_id, VTY_NEWLINE);
Pau Espin Pedrolfd815bb2019-08-30 18:32:42 +0200542 vty_out(vty, "%s MM State: %s, RAN Type: %s%s", pfx, mm_state_name,
543 get_value_string(sgsn_ran_type_names, mm->ran_type), VTY_NEWLINE);
Harald Welted193cb32010-05-17 22:58:03 +0200544
Pau Espin Pedrol3b848bd2019-08-30 18:06:35 +0200545 vty_out_rate_ctr_group(vty, " ", mm->ctrg);
Harald Welte8acd88f2010-05-18 10:57:45 +0200546
Harald Welted193cb32010-05-17 22:58:03 +0200547 if (pdp) {
548 struct sgsn_pdp_ctx *pdp;
549
550 llist_for_each_entry(pdp, &mm->pdp_list, list)
551 vty_dump_pdp(vty, " ", pdp);
552 }
553}
554
555DEFUN(show_sgsn, show_sgsn_cmd, "show sgsn",
556 SHOW_STR "Display information about the SGSN")
557{
Jacob Erlbeck80547992014-12-19 19:19:46 +0100558 if (sgsn->gsup_client) {
559 struct ipa_client_conn *link = sgsn->gsup_client->link;
560 vty_out(vty,
561 " Remote authorization: %sconnected to %s:%d via GSUP%s",
562 sgsn->gsup_client->is_connected ? "" : "not ",
563 link->addr, link->port,
564 VTY_NEWLINE);
565 }
Maxbaabc682017-10-20 13:39:57 +0200566 if (sgsn->gsn)
567 vty_out(vty, " GSN: signalling %s, user traffic %s%s",
568 inet_ntoa(sgsn->gsn->gsnc), inet_ntoa(sgsn->gsn->gsnu), VTY_NEWLINE);
569
Harald Welted193cb32010-05-17 22:58:03 +0200570 /* FIXME: statistics */
571 return CMD_SUCCESS;
572}
573
574#define MMCTX_STR "MM Context\n"
575#define INCLUDE_PDP_STR "Include PDP Context Information\n"
576
577#if 0
578DEFUN(show_mmctx_tlli, show_mmctx_tlli_cmd,
579 "show mm-context tlli HEX [pdp]",
580 SHOW_STR MMCTX_STR "Identify by TLLI\n" "TLLI\n" INCLUDE_PDP_STR)
581{
582 uint32_t tlli;
583 struct sgsn_mm_ctx *mm;
584
585 tlli = strtoul(argv[0], NULL, 16);
586 mm = sgsn_mm_ctx_by_tlli(tlli);
587 if (!mm) {
588 vty_out(vty, "No MM context for TLLI %08x%s",
589 tlli, VTY_NEWLINE);
590 return CMD_WARNING;
591 }
592 vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
593 return CMD_SUCCESS;
594}
595#endif
596
597DEFUN(swow_mmctx_imsi, show_mmctx_imsi_cmd,
598 "show mm-context imsi IMSI [pdp]",
599 SHOW_STR MMCTX_STR "Identify by IMSI\n" "IMSI of the MM Context\n"
600 INCLUDE_PDP_STR)
601{
602 struct sgsn_mm_ctx *mm;
603
604 mm = sgsn_mm_ctx_by_imsi(argv[0]);
605 if (!mm) {
606 vty_out(vty, "No MM context for IMSI %s%s",
607 argv[0], VTY_NEWLINE);
608 return CMD_WARNING;
609 }
610 vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
611 return CMD_SUCCESS;
612}
613
614DEFUN(swow_mmctx_all, show_mmctx_all_cmd,
615 "show mm-context all [pdp]",
616 SHOW_STR MMCTX_STR "All MM Contexts\n" INCLUDE_PDP_STR)
617{
618 struct sgsn_mm_ctx *mm;
619
620 llist_for_each_entry(mm, &sgsn_mm_ctxts, list)
621 vty_dump_mmctx(vty, "", mm, argv[0] ? 1 : 0);
622
623 return CMD_SUCCESS;
624}
625
Harald Welted193cb32010-05-17 22:58:03 +0200626DEFUN(show_pdpctx_all, show_pdpctx_all_cmd,
627 "show pdp-context all",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100628 SHOW_STR "Display information on PDP Context\n" "Show everything\n")
Harald Welted193cb32010-05-17 22:58:03 +0200629{
630 struct sgsn_pdp_ctx *pdp;
631
632 llist_for_each_entry(pdp, &sgsn_pdp_ctxts, g_list)
633 vty_dump_pdp(vty, "", pdp);
634
635 return CMD_SUCCESS;
636}
Harald Welte288be162010-05-01 16:48:27 +0200637
Harald Welte7f6da482013-03-19 11:00:13 +0100638
639DEFUN(imsi_acl, cfg_imsi_acl_cmd,
640 "imsi-acl (add|del) IMSI",
641 "Access Control List of foreign IMSIs\n"
642 "Add IMSI to ACL\n"
643 "Remove IMSI from ACL\n"
644 "IMSI of subscriber\n")
645{
Maxef38b4c2018-11-20 10:25:53 +0100646 char imsi_sanitized[GSM23003_IMSI_MAX_DIGITS + 1];
Harald Welte7f6da482013-03-19 11:00:13 +0100647 const char *op = argv[0];
Philipp Maier6ee49d82017-02-28 16:53:07 +0100648 const char *imsi = imsi_sanitized;
Maxf4fa6952018-01-15 12:12:51 +0100649 size_t len = strnlen(argv[1], GSM23003_IMSI_MAX_DIGITS + 1);
Harald Welte7f6da482013-03-19 11:00:13 +0100650 int rc;
651
Maxef38b4c2018-11-20 10:25:53 +0100652 memset(imsi_sanitized, '0', GSM23003_IMSI_MAX_DIGITS);
653 imsi_sanitized[GSM23003_IMSI_MAX_DIGITS] = '\0';
654
Philipp Maier6ee49d82017-02-28 16:53:07 +0100655 /* Sanitize IMSI */
Maxf4fa6952018-01-15 12:12:51 +0100656 if (len > GSM23003_IMSI_MAX_DIGITS) {
657 vty_out(vty, "%% IMSI (%s) too long (max %u digits) -- ignored!%s",
658 argv[1], GSM23003_IMSI_MAX_DIGITS, VTY_NEWLINE);
Philipp Maier6ee49d82017-02-28 16:53:07 +0100659 return CMD_WARNING;
660 }
Maxf4fa6952018-01-15 12:12:51 +0100661
662 osmo_strlcpy(imsi_sanitized + GSM23003_IMSI_MAX_DIGITS - len, argv[1],
663 sizeof(imsi_sanitized) - (GSM23003_IMSI_MAX_DIGITS - len));
Philipp Maier6ee49d82017-02-28 16:53:07 +0100664
Harald Welte7f6da482013-03-19 11:00:13 +0100665 if (!strcmp(op, "add"))
Jacob Erlbeck3b5d4072014-10-24 15:11:03 +0200666 rc = sgsn_acl_add(imsi, g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +0100667 else
Jacob Erlbeck3b5d4072014-10-24 15:11:03 +0200668 rc = sgsn_acl_del(imsi, g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +0100669
670 if (rc < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100671 vty_out(vty, "%% unable to %s ACL%s", op, VTY_NEWLINE);
Harald Welte7f6da482013-03-19 11:00:13 +0100672 return CMD_WARNING;
673 }
674
675 return CMD_SUCCESS;
676}
677
Max93408ae2016-06-28 14:10:16 +0200678DEFUN(cfg_encrypt, cfg_encrypt_cmd,
679 "encryption (GEA0|GEA1|GEA2|GEA3|GEA4)",
680 "Set encryption algorithm for SGSN\n"
681 "Use GEA0 (no encryption)\n"
682 "Use GEA1\nUse GEA2\nUse GEA3\nUse GEA4\n")
683{
Max93408ae2016-06-28 14:10:16 +0200684 enum gprs_ciph_algo c = get_string_value(gprs_cipher_names, argv[0]);
Max086067f2017-05-02 13:03:28 +0200685 if (c != GPRS_ALGO_GEA0) {
686 if (!gprs_cipher_supported(c)) {
687 vty_out(vty, "%% cipher %s is unsupported in current version%s", argv[0], VTY_NEWLINE);
688 return CMD_WARNING;
689 }
690
691 if (!g_cfg->require_authentication) {
692 vty_out(vty, "%% unable to use encryption %s without authentication: please adjust auth-policy%s",
693 argv[0], VTY_NEWLINE);
694 return CMD_WARNING;
695 }
Max93408ae2016-06-28 14:10:16 +0200696 }
697
698 g_cfg->cipher = c;
699
700 return CMD_SUCCESS;
701}
702
Vadim Yanitskiy794f4462019-05-27 05:39:06 +0700703DEFUN(cfg_authentication, cfg_authentication_cmd,
704 "authentication (optional|required)",
Pau Espin Pedrold1463bc2019-06-13 19:03:25 +0200705 "Whether to enforce MS authentication in GERAN (only with auth-policy remote)\n"
706 "Allow MS to attach via GERAN without authentication (default and only possible value for non-remote auth-policy)\n"
707 "Always require authentication (only available for auth-policy remote, default with that auth-policy)\n")
Vadim Yanitskiy794f4462019-05-27 05:39:06 +0700708{
709 int required = (argv[0][0] == 'r');
710
711 if (vty->type != VTY_FILE) {
712 if (g_cfg->auth_policy != SGSN_AUTH_POLICY_REMOTE && required) {
713 vty_out(vty, "%% Authentication is not possible without HLR, "
714 "consider setting 'auth-policy' to 'remote'%s",
715 VTY_NEWLINE);
716 return CMD_WARNING;
717 }
718 }
719
720 g_cfg->require_authentication = required;
721 return CMD_SUCCESS;
722}
723
Harald Welte3dfb5492013-03-19 11:48:54 +0100724DEFUN(cfg_auth_policy, cfg_auth_policy_cmd,
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100725 "auth-policy (accept-all|closed|acl-only|remote)",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100726 "Configure the Authorization policy of the SGSN. This setting determines which subscribers are"
727 " permitted to register to the network.\n"
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100728 "Accept all IMSIs (DANGEROUS)\n"
729 "Accept only home network subscribers or those in the ACL\n"
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100730 "Accept only subscribers in the ACL\n"
731 "Use remote subscription data only (HLR)\n")
Harald Welte3dfb5492013-03-19 11:48:54 +0100732{
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100733 int val = get_string_value(sgsn_auth_pol_strs, argv[0]);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100734 OSMO_ASSERT(val >= SGSN_AUTH_POLICY_OPEN && val <= SGSN_AUTH_POLICY_REMOTE);
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100735 g_cfg->auth_policy = val;
Jacob Erlbeck771573c2014-12-19 18:08:48 +0100736 g_cfg->require_update_location = (val == SGSN_AUTH_POLICY_REMOTE);
Harald Welte3dfb5492013-03-19 11:48:54 +0100737
738 return CMD_SUCCESS;
739}
740
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100741/* Subscriber */
Neels Hofmeyr396f2e62017-09-04 15:13:25 +0200742#include <osmocom/sgsn/gprs_subscriber.h>
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100743
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100744static void subscr_dump_full_vty(struct vty *vty, struct gprs_subscr *gsub, int pending)
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100745{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100746#if 0
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100747 char expire_time[200];
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100748#endif
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100749 struct gsm_auth_tuple *at;
750 int at_idx;
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100751 struct sgsn_subscriber_pdp_data *pdp;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100752
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100753 vty_out(vty, " Authorized: %d%s",
754 gsub->authorized, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100755 vty_out(vty, " LAC: %d/0x%x%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100756 gsub->lac, gsub->lac, VTY_NEWLINE);
757 vty_out(vty, " IMSI: %s%s", gsub->imsi, VTY_NEWLINE);
758 if (gsub->tmsi != GSM_RESERVED_TMSI)
759 vty_out(vty, " TMSI: %08X%s", gsub->tmsi,
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100760 VTY_NEWLINE);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100761 if (gsub->sgsn_data->msisdn_len > 0)
Holger Hans Peter Freytherf7b38262015-04-23 16:58:33 -0400762 vty_out(vty, " MSISDN (BCD): %s%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100763 osmo_hexdump(gsub->sgsn_data->msisdn,
764 gsub->sgsn_data->msisdn_len),
Holger Hans Peter Freytherf7b38262015-04-23 16:58:33 -0400765 VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100766
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100767 if (strlen(gsub->imei) > 0)
768 vty_out(vty, " IMEI: %s%s", gsub->imei, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100769
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100770 for (at_idx = 0; at_idx < ARRAY_SIZE(gsub->sgsn_data->auth_triplets);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100771 at_idx++) {
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100772 at = &gsub->sgsn_data->auth_triplets[at_idx];
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100773 if (at->key_seq == GSM_KEY_SEQ_INVAL)
774 continue;
775
776 vty_out(vty, " A3A8 tuple (used %d times): ",
777 at->use_count);
Harald Welte89837d42016-05-06 23:28:11 +0200778 vty_out(vty, " CKSN: %d, ",
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100779 at->key_seq);
Harald Welte89837d42016-05-06 23:28:11 +0200780 if (at->vec.auth_types & OSMO_AUTH_TYPE_GSM) {
781 vty_out(vty, "RAND: %s, ",
Max34604c22019-02-13 14:11:29 +0100782 osmo_hexdump_nospc(at->vec.rand,
Harald Welte89837d42016-05-06 23:28:11 +0200783 sizeof(at->vec.rand)));
784 vty_out(vty, "SRES: %s, ",
Max34604c22019-02-13 14:11:29 +0100785 osmo_hexdump_nospc(at->vec.sres,
Harald Welte89837d42016-05-06 23:28:11 +0200786 sizeof(at->vec.sres)));
787 vty_out(vty, "Kc: %s%s",
Max34604c22019-02-13 14:11:29 +0100788 osmo_hexdump_nospc(at->vec.kc,
Harald Welte89837d42016-05-06 23:28:11 +0200789 sizeof(at->vec.kc)), VTY_NEWLINE);
790 }
791 if (at->vec.auth_types & OSMO_AUTH_TYPE_UMTS) {
792 vty_out(vty, " AUTN: %s, ",
793 osmo_hexdump(at->vec.autn,
794 sizeof(at->vec.autn)));
795 vty_out(vty, "RES: %s, ",
Max34604c22019-02-13 14:11:29 +0100796 osmo_hexdump_nospc(at->vec.res, at->vec.res_len));
Harald Welte89837d42016-05-06 23:28:11 +0200797 vty_out(vty, "IK: %s, ",
Max34604c22019-02-13 14:11:29 +0100798 osmo_hexdump_nospc(at->vec.ik, sizeof(at->vec.ik)));
Harald Welte89837d42016-05-06 23:28:11 +0200799 vty_out(vty, "CK: %s, ",
Max34604c22019-02-13 14:11:29 +0100800 osmo_hexdump_nospc(at->vec.ck, sizeof(at->vec.ck)));
Harald Welte89837d42016-05-06 23:28:11 +0200801 }
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100802 }
803
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100804 llist_for_each_entry(pdp, &gsub->sgsn_data->pdp_list, list) {
Max34604c22019-02-13 14:11:29 +0100805 vty_out(vty, " PDP info: Id: %d, Type: 0x%04x, APN: '%s'",
806 pdp->context_id, pdp->pdp_type, pdp->apn_str);
807
808 if (pdp->qos_subscribed_len)
809 vty_out(vty, " QoS: %s", osmo_hexdump(pdp->qos_subscribed, pdp->qos_subscribed_len));
810
811 vty_out(vty, "%s", VTY_NEWLINE);
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100812 }
813
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100814#if 0
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100815 /* print the expiration time of a subscriber */
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100816 if (gsub->expire_lu) {
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100817 strftime(expire_time, sizeof(expire_time),
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100818 "%a, %d %b %Y %T %z", localtime(&gsub->expire_lu));
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100819 expire_time[sizeof(expire_time) - 1] = '\0';
820 vty_out(vty, " Expiration Time: %s%s", expire_time, VTY_NEWLINE);
821 }
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100822#endif
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100823
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100824 if (gsub->flags)
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100825 vty_out(vty, " Flags: %s%s%s%s%s%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100826 gsub->flags & GPRS_SUBSCRIBER_FIRST_CONTACT ?
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100827 "FIRST_CONTACT " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100828 gsub->flags & GPRS_SUBSCRIBER_CANCELLED ?
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100829 "CANCELLED " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100830 gsub->flags & GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING ?
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100831 "UPDATE_LOCATION_PENDING " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100832 gsub->flags & GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING ?
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100833 "AUTH_INFO_PENDING " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100834 gsub->flags & GPRS_SUBSCRIBER_ENABLE_PURGE ?
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100835 "ENABLE_PURGE " : "",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100836 VTY_NEWLINE);
837
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100838 vty_out(vty, " Use count: %u%s", gsub->use_count, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100839}
840
Neels Hofmeyr1a9414b2018-09-24 18:14:29 +0200841#define RESET_SGSN_STATE_STR \
842 "Remove all known subscribers, MM contexts and flush BSSGP queues." \
843 " Useful only when running tests against the SGSN\n"
844
Alexander Couzensc503f0a2018-08-07 17:50:04 +0200845DEFUN_HIDDEN(reset_sgsn_state,
846 reset_sgsn_state_cmd,
847 "reset sgsn state",
Neels Hofmeyr1a9414b2018-09-24 18:14:29 +0200848 RESET_SGSN_STATE_STR RESET_SGSN_STATE_STR RESET_SGSN_STATE_STR)
Alexander Couzensc503f0a2018-08-07 17:50:04 +0200849{
850 struct gprs_subscr *subscr, *tmp_subscr;
851 struct sgsn_mm_ctx *mm, *tmp_mm;
852
853 llist_for_each_entry_safe(mm, tmp_mm, &sgsn_mm_ctxts, list)
854 {
855 gsm0408_gprs_access_cancelled(mm, SGSN_ERROR_CAUSE_NONE);
856 }
857 vty_out(vty, "Cancelled MM Ctx. %s", VTY_NEWLINE);
858
859 llist_for_each_entry_safe(subscr, tmp_subscr, gprs_subscribers, entry) {
860 gprs_subscr_get(subscr);
861 gprs_subscr_cancel(subscr);
862 gprs_subscr_put(subscr);
863 }
864 vty_out(vty, "Removed all gprs subscribers.%s", VTY_NEWLINE);
865
866 bssgp_flush_all_queues();
867 vty_out(vty, "Flushed all BSSGPs queues.%s", VTY_NEWLINE);
868
Alexander Couzens35c34942018-09-17 04:39:14 +0200869 gtp_clear_queues(sgsn->gsn);
Alexander Couzensa66f0f22018-09-18 16:09:18 +0200870 vty_out(vty, "Flushed rx & tx queus towards the GGSN.%s", VTY_NEWLINE);
Alexander Couzens35c34942018-09-17 04:39:14 +0200871
Alexander Couzensc503f0a2018-08-07 17:50:04 +0200872 /* remove all queues to bssgp */
873 return CMD_SUCCESS;
874}
875
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100876DEFUN(show_subscr_cache,
877 show_subscr_cache_cmd,
878 "show subscriber cache",
879 SHOW_STR "Show information about subscribers\n"
880 "Display contents of subscriber cache\n")
881{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100882 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100883
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100884 llist_for_each_entry(subscr, gprs_subscribers, entry) {
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100885 vty_out(vty, " Subscriber:%s", VTY_NEWLINE);
886 subscr_dump_full_vty(vty, subscr, 0);
887 }
888
889 return CMD_SUCCESS;
890}
891
892#define UPDATE_SUBSCR_STR "update-subscriber imsi IMSI "
893#define UPDATE_SUBSCR_HELP "Update subscriber list\n" \
894 "Use the IMSI to select the subscriber\n" \
895 "The IMSI\n"
896
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100897#define UPDATE_SUBSCR_INSERT_HELP "Insert data into the subscriber record\n"
898
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100899DEFUN(update_subscr_insert_auth_triplet, update_subscr_insert_auth_triplet_cmd,
900 UPDATE_SUBSCR_STR "insert auth-triplet <1-5> sres SRES rand RAND kc KC",
901 UPDATE_SUBSCR_HELP
902 UPDATE_SUBSCR_INSERT_HELP
903 "Update authentication triplet\n"
904 "Triplet index\n"
905 "Set SRES value\nSRES value (4 byte) in hex\n"
906 "Set RAND value\nRAND value (16 byte) in hex\n"
907 "Set Kc value\nKc value (8 byte) in hex\n")
908{
909 const char *imsi = argv[0];
910 const int cksn = atoi(argv[1]) - 1;
911 const char *sres_str = argv[2];
912 const char *rand_str = argv[3];
913 const char *kc_str = argv[4];
914 struct gsm_auth_tuple at = {0,};
915
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100916 struct gprs_subscr *subscr;
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100917
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100918 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100919 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100920 vty_out(vty, "%% unable get subscriber record for %s%s",
921 imsi, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100922 return CMD_WARNING;
923 }
924
925 OSMO_ASSERT(subscr->sgsn_data);
926
Harald Welte121e9a42016-04-20 13:13:19 +0200927 if (osmo_hexparse(sres_str, &at.vec.sres[0], sizeof(at.vec.sres)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100928 vty_out(vty, "%% invalid SRES value '%s'%s",
929 sres_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100930 goto failed;
931 }
Harald Welte121e9a42016-04-20 13:13:19 +0200932 if (osmo_hexparse(rand_str, &at.vec.rand[0], sizeof(at.vec.rand)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100933 vty_out(vty, "%% invalid RAND value '%s'%s",
934 rand_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100935 goto failed;
936 }
Harald Welte121e9a42016-04-20 13:13:19 +0200937 if (osmo_hexparse(kc_str, &at.vec.kc[0], sizeof(at.vec.kc)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100938 vty_out(vty, "%% invalid Kc value '%s'%s",
939 kc_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100940 goto failed;
941 }
942 at.key_seq = cksn;
943
944 subscr->sgsn_data->auth_triplets[cksn] = at;
945 subscr->sgsn_data->auth_triplets_updated = 1;
946
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100947 gprs_subscr_put(subscr);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100948
949 return CMD_SUCCESS;
950
951failed:
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100952 gprs_subscr_put(subscr);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100953 return CMD_SUCCESS;
954}
955
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100956DEFUN(update_subscr_cancel, update_subscr_cancel_cmd,
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100957 UPDATE_SUBSCR_STR "cancel (update-procedure|subscription-withdraw)",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100958 UPDATE_SUBSCR_HELP
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100959 "Cancel (remove) subscriber record\n"
960 "The MS moved to another SGSN\n"
961 "The subscription is no longer valid\n")
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100962{
963 const char *imsi = argv[0];
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100964 const char *cancel_type = argv[1];
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100965
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100966 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100967
968 subscr = gprs_subscr_get_by_imsi(imsi);
969 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100970 vty_out(vty, "%% no subscriber record for %s%s",
971 imsi, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100972 return CMD_WARNING;
973 }
974
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100975 if (strcmp(cancel_type, "update-procedure") == 0)
976 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
977 else
978 subscr->sgsn_data->error_cause = GMM_CAUSE_IMPL_DETACHED;
979
Jacob Erlbeck37139e52015-01-23 13:52:55 +0100980 gprs_subscr_cancel(subscr);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100981 gprs_subscr_put(subscr);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100982
983 return CMD_SUCCESS;
984}
985
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100986DEFUN(update_subscr_create, update_subscr_create_cmd,
987 UPDATE_SUBSCR_STR "create",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100988 UPDATE_SUBSCR_HELP
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100989 "Create a subscriber entry\n")
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100990{
991 const char *imsi = argv[0];
992
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100993 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100994
995 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100996 if (subscr) {
997 vty_out(vty, "%% subscriber record already exists for %s%s",
998 imsi, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100999 return CMD_WARNING;
1000 }
1001
Jacob Erlbeckd9193432015-01-19 14:11:46 +01001002 subscr = gprs_subscr_get_or_create(imsi);
1003 subscr->keep_in_ram = 1;
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001004 gprs_subscr_put(subscr);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001005
1006 return CMD_SUCCESS;
1007}
1008
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001009DEFUN(update_subscr_destroy, update_subscr_destroy_cmd,
1010 UPDATE_SUBSCR_STR "destroy",
1011 UPDATE_SUBSCR_HELP
1012 "Destroy a subscriber entry\n")
1013{
1014 const char *imsi = argv[0];
1015
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001016 struct gprs_subscr *subscr;
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001017
1018 subscr = gprs_subscr_get_by_imsi(imsi);
1019 if (!subscr) {
1020 vty_out(vty, "%% subscriber record does not exist for %s%s",
1021 imsi, VTY_NEWLINE);
1022 return CMD_WARNING;
1023 }
1024
1025 subscr->keep_in_ram = 0;
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +01001026 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001027 gprs_subscr_cancel(subscr);
1028 if (subscr->use_count > 1)
1029 vty_out(vty, "%% subscriber is still in use%s",
1030 VTY_NEWLINE);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001031 gprs_subscr_put(subscr);
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001032
1033 return CMD_SUCCESS;
1034}
1035
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001036#define UL_ERR_STR "system-failure|data-missing|unexpected-data-value|" \
1037 "unknown-subscriber|roaming-not-allowed"
1038
1039#define UL_ERR_HELP \
1040 "Force error code SystemFailure\n" \
1041 "Force error code DataMissing\n" \
1042 "Force error code UnexpectedDataValue\n" \
1043 "Force error code UnknownSubscriber\n" \
1044 "Force error code RoamingNotAllowed\n"
1045
1046DEFUN(update_subscr_update_location_result, update_subscr_update_location_result_cmd,
1047 UPDATE_SUBSCR_STR "update-location-result (ok|" UL_ERR_STR ")",
1048 UPDATE_SUBSCR_HELP
1049 "Complete the update location procedure\n"
1050 "The update location request succeeded\n"
1051 UL_ERR_HELP)
1052{
1053 const char *imsi = argv[0];
1054 const char *ret_code_str = argv[1];
1055
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001056 struct gprs_subscr *subscr;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001057
Jacob Erlbeckd6267d12015-01-19 11:10:04 +01001058 const struct value_string cause_mapping[] = {
1059 { GMM_CAUSE_NET_FAIL, "system-failure" },
1060 { GMM_CAUSE_INV_MAND_INFO, "data-missing" },
1061 { GMM_CAUSE_PROTO_ERR_UNSPEC, "unexpected-data-value" },
1062 { GMM_CAUSE_IMSI_UNKNOWN, "unknown-subscriber" },
1063 { GMM_CAUSE_GPRS_NOTALLOWED, "roaming-not-allowed" },
1064 { 0, NULL }
1065 };
1066
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001067 subscr = gprs_subscr_get_by_imsi(imsi);
1068 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +01001069 vty_out(vty, "%% unable to get subscriber record for %s%s",
1070 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001071 return CMD_WARNING;
1072 }
Jacob Erlbeckd6267d12015-01-19 11:10:04 +01001073
1074 if (strcmp(ret_code_str, "ok") == 0) {
1075 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001076 subscr->authorized = 1;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +01001077 } else {
1078 subscr->sgsn_data->error_cause =
1079 get_string_value(cause_mapping, ret_code_str);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001080 subscr->authorized = 0;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +01001081 }
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001082
1083 gprs_subscr_update(subscr);
1084
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001085 gprs_subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001086
1087 return CMD_SUCCESS;
1088}
1089
1090DEFUN(update_subscr_update_auth_info, update_subscr_update_auth_info_cmd,
1091 UPDATE_SUBSCR_STR "update-auth-info",
1092 UPDATE_SUBSCR_HELP
1093 "Complete the send authentication info procedure\n")
1094{
1095 const char *imsi = argv[0];
1096
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001097 struct gprs_subscr *subscr;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001098
1099 subscr = gprs_subscr_get_by_imsi(imsi);
1100 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +01001101 vty_out(vty, "%% unable to get subscriber record for %s%s",
1102 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001103 return CMD_WARNING;
1104 }
1105
1106 gprs_subscr_update_auth_info(subscr);
1107
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001108 gprs_subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001109
1110 return CMD_SUCCESS;
1111}
1112
Stefan Sperling88220092018-12-11 14:42:00 +01001113DEFUN(cfg_gsup_ipa_name,
1114 cfg_gsup_ipa_name_cmd,
1115 "gsup ipa-name NAME",
1116 "GSUP Parameters\n"
1117 "Set the IPA name of this SGSN\n"
1118 "A unique name for this SGSN. For example: PLMN + redundancy server number: SGSN-901-70-0. "
1119 "This name is used for GSUP routing and must be set if more than one SGSN is connected to the network. "
1120 "The default is 'SGSN-00-00-00-00-00-00'.\n")
1121{
1122 if (vty->type != VTY_FILE) {
1123 vty_out(vty, "The IPA name cannot be changed at run-time; "
1124 "It can only be set in the configuraton file.%s", VTY_NEWLINE);
1125 return CMD_WARNING;
1126 }
1127
1128 g_cfg->sgsn_ipa_name = talloc_strdup(tall_vty_ctx, argv[0]);
1129 return CMD_SUCCESS;
1130}
1131
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001132DEFUN(cfg_gsup_remote_ip, cfg_gsup_remote_ip_cmd,
1133 "gsup remote-ip A.B.C.D",
1134 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001135 "Set the IP address of the remote GSUP server (e.g. OsmoHLR)."
1136 " This setting only applies if 'auth-policy remote' is used.\n"
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001137 "IPv4 Address\n")
1138{
1139 inet_aton(argv[0], &g_cfg->gsup_server_addr.sin_addr);
1140
1141 return CMD_SUCCESS;
1142}
1143
1144DEFUN(cfg_gsup_remote_port, cfg_gsup_remote_port_cmd,
1145 "gsup remote-port <0-65535>",
1146 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001147 "Set the TCP port of the remote GSUP server, see also 'gsup remote-ip'\n"
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001148 "Remote TCP port\n")
1149{
1150 g_cfg->gsup_server_port = atoi(argv[0]);
1151
1152 return CMD_SUCCESS;
1153}
1154
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001155DEFUN(cfg_gsup_oap_id, cfg_gsup_oap_id_cmd,
1156 "gsup oap-id <0-65535>",
1157 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001158 "Set the OAP client ID for authentication on the GSUP protocol."
1159 " This setting only applies if 'auth-policy remote' is used.\n"
1160 "OAP client ID (0 == disabled)\n")
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001161{
1162 /* VTY ensures range */
1163 g_cfg->oap.client_id = (uint16_t)atoi(argv[0]);
1164 return CMD_SUCCESS;
1165}
1166
1167DEFUN(cfg_gsup_oap_k, cfg_gsup_oap_k_cmd,
1168 "gsup oap-k K",
1169 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001170 "Set the OAP shared secret key K for authentication on the GSUP protocol."
1171 " This setting only applies if auth-policy remote is used.\n"
1172 "K value (16 byte) hex\n")
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001173{
1174 const char *k = argv[0];
1175
1176 g_cfg->oap.secret_k_present = 0;
1177
1178 if ((!k) || (strlen(k) == 0))
1179 goto disable;
1180
1181 int k_len = osmo_hexparse(k,
1182 g_cfg->oap.secret_k,
1183 sizeof(g_cfg->oap.secret_k));
1184 if (k_len != 16) {
1185 vty_out(vty, "%% need exactly 16 octets for oap-k, got %d.%s",
1186 k_len, VTY_NEWLINE);
1187 goto disable;
1188 }
1189
1190 g_cfg->oap.secret_k_present = 1;
1191 return CMD_SUCCESS;
1192
1193disable:
1194 if (g_cfg->oap.client_id > 0) {
1195 vty_out(vty, "%% OAP client ID set, but invalid oap-k value disables OAP.%s",
1196 VTY_NEWLINE);
1197 return CMD_WARNING;
1198 }
1199 return CMD_SUCCESS;
1200}
1201
1202DEFUN(cfg_gsup_oap_opc, cfg_gsup_oap_opc_cmd,
1203 "gsup oap-opc OPC",
1204 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001205 "Set the OAP shared secret OPC for authentication on the GSUP protocol."
1206 " This setting only applies if auth-policy remote is used.\n"
1207 "OPC value (16 byte) hex\n")
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001208{
1209 const char *opc = argv[0];
1210
1211 g_cfg->oap.secret_opc_present = 0;
1212
1213 if ((!opc) || (strlen(opc) == 0))
1214 goto disable;
1215
1216 int opc_len = osmo_hexparse(opc,
1217 g_cfg->oap.secret_opc,
1218 sizeof(g_cfg->oap.secret_opc));
1219 if (opc_len != 16) {
1220 vty_out(vty, "%% need exactly 16 octets for oap-opc, got %d.%s",
1221 opc_len, VTY_NEWLINE);
1222 goto disable;
1223 }
1224
1225 g_cfg->oap.secret_opc_present = 1;
1226 return CMD_SUCCESS;
1227
1228disable:
1229 if (g_cfg->oap.client_id > 0) {
1230 vty_out(vty, "%% OAP client ID set, but invalid oap-opc value disables OAP.%s",
1231 VTY_NEWLINE);
1232 return CMD_WARNING;
1233 }
1234 return CMD_SUCCESS;
1235}
1236
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001237DEFUN(cfg_apn_name, cfg_apn_name_cmd,
1238 "access-point-name NAME",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001239 "Globally allow the given APN name for all subscribers.\n"
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001240 "Add this NAME to the list\n")
1241{
1242 return add_apn_ggsn_mapping(vty, argv[0], "", 0);
1243}
1244
1245DEFUN(cfg_no_apn_name, cfg_no_apn_name_cmd,
1246 "no access-point-name NAME",
1247 NO_STR "Configure a global list of allowed APNs\n"
1248 "Remove entry with NAME\n")
1249{
1250 struct apn_ctx *apn_ctx = sgsn_apn_ctx_by_name(argv[0], "");
1251 if (!apn_ctx)
1252 return CMD_SUCCESS;
1253
1254 sgsn_apn_ctx_free(apn_ctx);
1255 return CMD_SUCCESS;
1256}
1257
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001258DEFUN(cfg_cdr_filename, cfg_cdr_filename_cmd,
1259 "cdr filename NAME",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001260 "CDR\n"
1261 "Set the file name for the call-data-record file, logging the data usage of each subscriber.\n"
1262 "filename\n")
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001263{
1264 talloc_free(g_cfg->cdr.filename);
1265 g_cfg->cdr.filename = talloc_strdup(tall_vty_ctx, argv[0]);
1266 return CMD_SUCCESS;
1267}
1268
1269DEFUN(cfg_no_cdr_filename, cfg_no_cdr_filename_cmd,
1270 "no cdr filename",
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +01001271 NO_STR "CDR\nDisable saving CDR to file\n")
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001272{
1273 talloc_free(g_cfg->cdr.filename);
1274 g_cfg->cdr.filename = NULL;
1275 return CMD_SUCCESS;
1276}
1277
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +01001278DEFUN(cfg_cdr_trap, cfg_cdr_trap_cmd,
1279 "cdr trap",
1280 "CDR\nEnable sending CDR via TRAP CTRL messages\n")
1281{
1282 g_cfg->cdr.trap = true;
1283 return CMD_SUCCESS;
1284}
1285
1286DEFUN(cfg_no_cdr_trap, cfg_no_cdr_trap_cmd,
1287 "no cdr trap",
1288 NO_STR "CDR\nDisable sending CDR via TRAP CTRL messages\n")
1289{
1290 g_cfg->cdr.trap = false;
1291 return CMD_SUCCESS;
1292}
1293
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001294DEFUN(cfg_cdr_interval, cfg_cdr_interval_cmd,
1295 "cdr interval <1-2147483647>",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001296 "CDR\n"
1297 "Set the interval for the call-data-record file\n"
1298 "interval in seconds\n")
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001299{
1300 g_cfg->cdr.interval = atoi(argv[0]);
1301 return CMD_SUCCESS;
1302}
1303
Philippf1f34362016-08-26 17:00:21 +02001304#define COMPRESSION_STR "Configure compression\n"
1305DEFUN(cfg_no_comp_rfc1144, cfg_no_comp_rfc1144_cmd,
1306 "no compression rfc1144",
1307 NO_STR COMPRESSION_STR "disable rfc1144 TCP/IP header compression\n")
1308{
1309 g_cfg->pcomp_rfc1144.active = 0;
1310 g_cfg->pcomp_rfc1144.passive = 0;
1311 return CMD_SUCCESS;
1312}
1313
1314DEFUN(cfg_comp_rfc1144, cfg_comp_rfc1144_cmd,
1315 "compression rfc1144 active slots <1-256>",
1316 COMPRESSION_STR
Ruben Undheim55fcf112018-09-25 22:59:34 +02001317 "RFC1144 Header compression scheme\n"
Philippf1f34362016-08-26 17:00:21 +02001318 "Compression is actively proposed\n"
1319 "Number of compression state slots\n"
1320 "Number of compression state slots\n")
1321{
1322 g_cfg->pcomp_rfc1144.active = 1;
1323 g_cfg->pcomp_rfc1144.passive = 1;
1324 g_cfg->pcomp_rfc1144.s01 = atoi(argv[0]) - 1;
1325 return CMD_SUCCESS;
1326}
1327
1328DEFUN(cfg_comp_rfc1144p, cfg_comp_rfc1144p_cmd,
1329 "compression rfc1144 passive",
1330 COMPRESSION_STR
Ruben Undheim55fcf112018-09-25 22:59:34 +02001331 "RFC1144 Header compression scheme\n"
Philippf1f34362016-08-26 17:00:21 +02001332 "Compression is available on request\n")
1333{
1334 g_cfg->pcomp_rfc1144.active = 0;
1335 g_cfg->pcomp_rfc1144.passive = 1;
1336 return CMD_SUCCESS;
1337}
1338
Philipp73f83d52016-09-02 13:38:01 +02001339DEFUN(cfg_no_comp_v42bis, cfg_no_comp_v42bis_cmd,
1340 "no compression v42bis",
1341 NO_STR COMPRESSION_STR "disable V.42bis data compression\n")
1342{
1343 g_cfg->dcomp_v42bis.active = 0;
1344 g_cfg->dcomp_v42bis.passive = 0;
1345 return CMD_SUCCESS;
1346}
1347
1348DEFUN(cfg_comp_v42bis, cfg_comp_v42bis_cmd,
1349 "compression v42bis active direction (ms|sgsn|both) codewords <512-65535> strlen <6-250>",
1350 COMPRESSION_STR
Ruben Undheim55fcf112018-09-25 22:59:34 +02001351 "V.42bis data compression scheme\n"
Philipp73f83d52016-09-02 13:38:01 +02001352 "Compression is actively proposed\n"
1353 "Direction in which the compression shall be active (p0)\n"
1354 "Compress ms->sgsn direction only\n"
1355 "Compress sgsn->ms direction only\n"
1356 "Both directions\n"
1357 "Number of codewords (p1)\n"
1358 "Number of codewords\n"
1359 "Maximum string length (p2)\n" "Maximum string length\n")
1360{
1361 g_cfg->dcomp_v42bis.active = 1;
1362 g_cfg->dcomp_v42bis.passive = 1;
1363
1364 switch (argv[0][0]) {
1365 case 'm':
1366 g_cfg->dcomp_v42bis.p0 = 1;
1367 break;
1368 case 's':
1369 g_cfg->dcomp_v42bis.p0 = 2;
1370 break;
1371 case 'b':
1372 g_cfg->dcomp_v42bis.p0 = 3;
1373 break;
1374 }
1375
1376 g_cfg->dcomp_v42bis.p1 = atoi(argv[1]);
1377 g_cfg->dcomp_v42bis.p2 = atoi(argv[2]);
1378 return CMD_SUCCESS;
1379}
1380
1381DEFUN(cfg_comp_v42bisp, cfg_comp_v42bisp_cmd,
1382 "compression v42bis passive",
1383 COMPRESSION_STR
Ruben Undheim55fcf112018-09-25 22:59:34 +02001384 "V.42bis data compression scheme\n"
Philipp73f83d52016-09-02 13:38:01 +02001385 "Compression is available on request\n")
1386{
1387 g_cfg->dcomp_v42bis.active = 0;
1388 g_cfg->dcomp_v42bis.passive = 1;
1389 return CMD_SUCCESS;
1390}
1391
Pau Espin Pedrol2c908992019-08-19 19:06:06 +02001392#if BUILD_IU
1393DEFUN(cfg_sgsn_cs7_instance_iu,
1394 cfg_sgsn_cs7_instance_iu_cmd,
1395 "cs7-instance-iu <0-15>",
1396 "Set SS7 to be used by the Iu-Interface.\n" "SS7 instance reference number (default: 0)\n")
1397{
1398 g_cfg->iu.cs7_instance = atoi(argv[0]);
1399 return CMD_SUCCESS;
1400}
1401#endif
1402
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001403int sgsn_vty_init(struct sgsn_config *cfg)
Harald Welte288be162010-05-01 16:48:27 +02001404{
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001405 g_cfg = cfg;
1406
Pau Espin Pedrola299d652019-08-14 19:11:10 +02001407 g_cfg->T_defs = sgsn_T_defs;
1408 osmo_tdefs_reset(g_cfg->T_defs);
1409
Harald Welted193cb32010-05-17 22:58:03 +02001410 install_element_ve(&show_sgsn_cmd);
1411 //install_element_ve(&show_mmctx_tlli_cmd);
1412 install_element_ve(&show_mmctx_imsi_cmd);
1413 install_element_ve(&show_mmctx_all_cmd);
1414 install_element_ve(&show_pdpctx_all_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001415 install_element_ve(&show_subscr_cache_cmd);
Pau Espin Pedrola299d652019-08-14 19:11:10 +02001416 install_element_ve(&show_timer_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001417
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01001418 install_element(ENABLE_NODE, &update_subscr_insert_auth_triplet_cmd);
Jacob Erlbeckd9193432015-01-19 14:11:46 +01001419 install_element(ENABLE_NODE, &update_subscr_create_cmd);
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001420 install_element(ENABLE_NODE, &update_subscr_destroy_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001421 install_element(ENABLE_NODE, &update_subscr_cancel_cmd);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001422 install_element(ENABLE_NODE, &update_subscr_update_location_result_cmd);
1423 install_element(ENABLE_NODE, &update_subscr_update_auth_info_cmd);
Alexander Couzensc503f0a2018-08-07 17:50:04 +02001424 install_element(ENABLE_NODE, &reset_sgsn_state_cmd);
Harald Welte288be162010-05-01 16:48:27 +02001425
1426 install_element(CONFIG_NODE, &cfg_sgsn_cmd);
1427 install_node(&sgsn_node, config_write_sgsn);
Harald Weltee300d002010-06-02 12:41:34 +02001428 install_element(SGSN_NODE, &cfg_sgsn_bind_addr_cmd);
Harald Welted193cb32010-05-17 22:58:03 +02001429 install_element(SGSN_NODE, &cfg_ggsn_remote_ip_cmd);
1430 //install_element(SGSN_NODE, &cfg_ggsn_remote_port_cmd);
1431 install_element(SGSN_NODE, &cfg_ggsn_gtp_version_cmd);
Pau Espin Pedrolfa120102018-07-09 20:37:47 +02001432 install_element(SGSN_NODE, &cfg_ggsn_echo_interval_cmd);
Pau Espin Pedrola83850c2018-07-10 12:43:59 +02001433 install_element(SGSN_NODE, &cfg_ggsn_no_echo_interval_cmd);
Harald Welte7f6da482013-03-19 11:00:13 +01001434 install_element(SGSN_NODE, &cfg_imsi_acl_cmd);
Harald Welte3dfb5492013-03-19 11:48:54 +01001435 install_element(SGSN_NODE, &cfg_auth_policy_cmd);
Vadim Yanitskiy794f4462019-05-27 05:39:06 +07001436 install_element(SGSN_NODE, &cfg_authentication_cmd);
Max93408ae2016-06-28 14:10:16 +02001437 install_element(SGSN_NODE, &cfg_encrypt_cmd);
Stefan Sperling88220092018-12-11 14:42:00 +01001438 install_element(SGSN_NODE, &cfg_gsup_ipa_name_cmd);
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001439 install_element(SGSN_NODE, &cfg_gsup_remote_ip_cmd);
1440 install_element(SGSN_NODE, &cfg_gsup_remote_port_cmd);
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001441 install_element(SGSN_NODE, &cfg_gsup_oap_id_cmd);
1442 install_element(SGSN_NODE, &cfg_gsup_oap_k_cmd);
1443 install_element(SGSN_NODE, &cfg_gsup_oap_opc_cmd);
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +01001444 install_element(SGSN_NODE, &cfg_apn_ggsn_cmd);
1445 install_element(SGSN_NODE, &cfg_apn_imsi_ggsn_cmd);
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001446 install_element(SGSN_NODE, &cfg_apn_name_cmd);
1447 install_element(SGSN_NODE, &cfg_no_apn_name_cmd);
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001448 install_element(SGSN_NODE, &cfg_cdr_filename_cmd);
1449 install_element(SGSN_NODE, &cfg_no_cdr_filename_cmd);
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +01001450 install_element(SGSN_NODE, &cfg_cdr_trap_cmd);
1451 install_element(SGSN_NODE, &cfg_no_cdr_trap_cmd);
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001452 install_element(SGSN_NODE, &cfg_cdr_interval_cmd);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001453 install_element(SGSN_NODE, &cfg_ggsn_dynamic_lookup_cmd);
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +08001454 install_element(SGSN_NODE, &cfg_grx_ggsn_cmd);
Harald Welte288be162010-05-01 16:48:27 +02001455
Pau Espin Pedrola299d652019-08-14 19:11:10 +02001456 install_element(SGSN_NODE, &cfg_sgsn_timer_cmd);
Harald Welte94508822015-08-15 19:08:21 +02001457
Philippf1f34362016-08-26 17:00:21 +02001458 install_element(SGSN_NODE, &cfg_no_comp_rfc1144_cmd);
1459 install_element(SGSN_NODE, &cfg_comp_rfc1144_cmd);
1460 install_element(SGSN_NODE, &cfg_comp_rfc1144p_cmd);
Philipp73f83d52016-09-02 13:38:01 +02001461 install_element(SGSN_NODE, &cfg_no_comp_v42bis_cmd);
1462 install_element(SGSN_NODE, &cfg_comp_v42bis_cmd);
1463 install_element(SGSN_NODE, &cfg_comp_v42bisp_cmd);
Neels Hofmeyr2188a772016-05-20 21:59:55 +02001464
1465#ifdef BUILD_IU
Pau Espin Pedrol2c908992019-08-19 19:06:06 +02001466 install_element(SGSN_NODE, &cfg_sgsn_cs7_instance_iu_cmd);
Neels Hofmeyra7a39472017-07-05 15:19:52 +02001467 ranap_iu_vty_init(SGSN_NODE, &g_cfg->iu.rab_assign_addr_enc);
Neels Hofmeyr2188a772016-05-20 21:59:55 +02001468#endif
Harald Welte288be162010-05-01 16:48:27 +02001469 return 0;
1470}
1471
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001472int sgsn_parse_config(const char *config_file)
Harald Welte288be162010-05-01 16:48:27 +02001473{
1474 int rc;
1475
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001476 /* make sure sgsn_vty_init() was called before this */
1477 OSMO_ASSERT(g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +01001478
Harald Weltedcccb182010-05-16 20:52:23 +02001479 rc = vty_read_config_file(config_file, NULL);
Harald Welte288be162010-05-01 16:48:27 +02001480 if (rc < 0) {
1481 fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
1482 return rc;
1483 }
1484
Neels Hofmeyr27355c92017-02-24 06:28:31 +01001485 if (g_cfg->auth_policy == SGSN_AUTH_POLICY_REMOTE
1486 && !(g_cfg->gsup_server_addr.sin_addr.s_addr
1487 && g_cfg->gsup_server_port)) {
1488 fprintf(stderr, "Configuration error:"
1489 " 'auth-policy remote' requires both"
1490 " 'gsup remote-ip' and 'gsup remote-port'\n");
1491 return -EINVAL;
1492 }
1493
Harald Welte288be162010-05-01 16:48:27 +02001494 return 0;
1495}