blob: 17b64c8902167d29cd873170aa662ae49fd06dd2 [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)" },
Alexander Couzens3bad31b2019-09-11 02:17:31 +0200107 /* non spec timers */
108 { .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 +0200109 {}
110};
111
112DEFUN(show_timer, show_timer_cmd,
113 "show timer " OSMO_TDEF_VTY_ARG_T_OPTIONAL,
114 SHOW_STR "Show timers\n"
115 OSMO_TDEF_VTY_DOC_T)
116{
117 const char *T_arg = argc > 0 ? argv[0] : NULL;
118 return osmo_tdef_vty_show_cmd(vty, g_cfg->T_defs, T_arg, NULL);
Harald Welte94508822015-08-15 19:08:21 +0200119}
120
Pau Espin Pedrola299d652019-08-14 19:11:10 +0200121DEFUN(cfg_sgsn_timer, cfg_sgsn_timer_cmd,
122 "timer " OSMO_TDEF_VTY_ARG_SET_OPTIONAL,
123 "Configure or show timers\n"
124 OSMO_TDEF_VTY_DOC_SET)
125{
126 /* If any arguments are missing, redirect to 'show' */
127 if (argc < 2)
128 return show_timer(self, vty, argc, argv);
129 return osmo_tdef_vty_set_cmd(vty, g_cfg->T_defs, argv);
130}
Harald Welte94508822015-08-15 19:08:21 +0200131
Holger Hans Peter Freythera2730302014-03-23 18:08:26 +0100132char *gprs_pdpaddr2str(uint8_t *pdpa, uint8_t len)
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200133{
134 static char str[INET6_ADDRSTRLEN + 10];
135
136 if (!pdpa || len < 2)
137 return "none";
138
139 switch (pdpa[0] & 0x0f) {
140 case PDP_TYPE_ORG_IETF:
141 switch (pdpa[1]) {
142 case PDP_TYPE_N_IETF_IPv4:
143 if (len < 2 + 4)
144 break;
145 strcpy(str, "IPv4 ");
146 inet_ntop(AF_INET, pdpa+2, str+5, sizeof(str)-5);
147 return str;
148 case PDP_TYPE_N_IETF_IPv6:
149 if (len < 2 + 8)
150 break;
151 strcpy(str, "IPv6 ");
152 inet_ntop(AF_INET6, pdpa+2, str+5, sizeof(str)-5);
153 return str;
154 default:
155 break;
156 }
157 break;
158 case PDP_TYPE_ORG_ETSI:
159 if (pdpa[1] == PDP_TYPE_N_ETSI_PPP)
160 return "PPP";
161 break;
162 default:
163 break;
164 }
165
166 return "invalid";
167}
168
Harald Welte288be162010-05-01 16:48:27 +0200169static struct cmd_node sgsn_node = {
170 SGSN_NODE,
Harald Welte570ce242012-08-17 13:16:10 +0200171 "%s(config-sgsn)# ",
Harald Welte288be162010-05-01 16:48:27 +0200172 1,
173};
174
175static int config_write_sgsn(struct vty *vty)
176{
Harald Welte77289c22010-05-18 14:32:29 +0200177 struct sgsn_ggsn_ctx *gctx;
Harald Welte7f6da482013-03-19 11:00:13 +0100178 struct imsi_acl_entry *acl;
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100179 struct apn_ctx *actx;
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800180 struct ares_addr_node *server;
Harald Welte288be162010-05-01 16:48:27 +0200181
182 vty_out(vty, "sgsn%s", VTY_NEWLINE);
183
Harald Weltee300d002010-06-02 12:41:34 +0200184 vty_out(vty, " gtp local-ip %s%s",
185 inet_ntoa(g_cfg->gtp_listenaddr.sin_addr), VTY_NEWLINE);
186
Harald Welted193cb32010-05-17 22:58:03 +0200187 llist_for_each_entry(gctx, &sgsn_ggsn_ctxts, list) {
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800188 if (gctx->id == UINT32_MAX)
189 continue;
190
Harald Welteff3bde82010-05-19 15:09:09 +0200191 vty_out(vty, " ggsn %u remote-ip %s%s", gctx->id,
Harald Welted193cb32010-05-17 22:58:03 +0200192 inet_ntoa(gctx->remote_addr), VTY_NEWLINE);
Harald Welteff3bde82010-05-19 15:09:09 +0200193 vty_out(vty, " ggsn %u gtp-version %u%s", gctx->id,
Harald Welted193cb32010-05-17 22:58:03 +0200194 gctx->gtp_version, VTY_NEWLINE);
Pau Espin Pedrolaa89f5d2019-08-28 16:08:45 +0200195 if (gctx->echo_interval)
196 vty_out(vty, " ggsn %u echo-interval %u%s",
Pau Espin Pedrolfa120102018-07-09 20:37:47 +0200197 gctx->id, gctx->echo_interval, VTY_NEWLINE);
Pau Espin Pedrola83850c2018-07-10 12:43:59 +0200198 else
199 vty_out(vty, " ggsn %u no echo-interval%s",
200 gctx->id, VTY_NEWLINE);
Harald Welte288be162010-05-01 16:48:27 +0200201 }
202
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800203 if (sgsn->cfg.dynamic_lookup)
204 vty_out(vty, " ggsn dynamic%s", VTY_NEWLINE);
205
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800206 for (server = sgsn->ares_servers; server; server = server->next)
207 vty_out(vty, " grx-dns-add %s%s", inet_ntoa(server->addr.addr4), VTY_NEWLINE);
208
Max93408ae2016-06-28 14:10:16 +0200209 if (g_cfg->cipher != GPRS_ALGO_GEA0)
210 vty_out(vty, " encryption %s%s",
211 get_value_string(gprs_cipher_names, g_cfg->cipher),
212 VTY_NEWLINE);
Stefan Sperling88220092018-12-11 14:42:00 +0100213 if (g_cfg->sgsn_ipa_name)
214 vty_out(vty, " gsup ipa-name %s%s", g_cfg->sgsn_ipa_name, VTY_NEWLINE);
Jacob Erlbeck39f040d2014-12-18 12:46:47 +0100215 if (g_cfg->gsup_server_addr.sin_addr.s_addr)
216 vty_out(vty, " gsup remote-ip %s%s",
217 inet_ntoa(g_cfg->gsup_server_addr.sin_addr), VTY_NEWLINE);
218 if (g_cfg->gsup_server_port)
219 vty_out(vty, " gsup remote-port %d%s",
220 g_cfg->gsup_server_port, VTY_NEWLINE);
Pau Espin Pedrold1463bc2019-06-13 19:03:25 +0200221 if (g_cfg->auth_policy == SGSN_AUTH_POLICY_REMOTE && !g_cfg->require_authentication)
222 vty_out(vty, " authentication optional%s", VTY_NEWLINE);
Max176b62a2016-07-04 11:09:07 +0200223 vty_out(vty, " auth-policy %s%s",
224 get_value_string(sgsn_auth_pol_strs, g_cfg->auth_policy),
225 VTY_NEWLINE);
Neels Hofmeyr568a7272015-10-12 11:57:38 +0200226
227 vty_out(vty, " gsup oap-id %d%s",
228 (int)g_cfg->oap.client_id, VTY_NEWLINE);
229 if (g_cfg->oap.secret_k_present != 0)
230 vty_out(vty, " gsup oap-k %s%s",
231 osmo_hexdump_nospc(g_cfg->oap.secret_k, sizeof(g_cfg->oap.secret_k)),
232 VTY_NEWLINE);
233 if (g_cfg->oap.secret_opc_present != 0)
234 vty_out(vty, " gsup oap-opc %s%s",
235 osmo_hexdump_nospc(g_cfg->oap.secret_opc, sizeof(g_cfg->oap.secret_opc)),
236 VTY_NEWLINE);
237
Harald Welte7f6da482013-03-19 11:00:13 +0100238 llist_for_each_entry(acl, &g_cfg->imsi_acl, list)
239 vty_out(vty, " imsi-acl add %s%s", acl->imsi, VTY_NEWLINE);
240
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100241 if (llist_empty(&sgsn_apn_ctxts))
242 vty_out(vty, " ! apn * ggsn 0%s", VTY_NEWLINE);
243 llist_for_each_entry(actx, &sgsn_apn_ctxts, list) {
244 if (strlen(actx->imsi_prefix) > 0)
Holger Hans Peter Freytherb7ae0b32015-05-29 15:11:55 +0200245 vty_out(vty, " apn %s imsi-prefix %s ggsn %u%s",
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100246 actx->name, actx->imsi_prefix, actx->ggsn->id,
247 VTY_NEWLINE);
248 else
Holger Hans Peter Freytherb7ae0b32015-05-29 15:11:55 +0200249 vty_out(vty, " apn %s ggsn %u%s", actx->name,
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100250 actx->ggsn->id, VTY_NEWLINE);
251 }
252
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +0200253 if (g_cfg->cdr.filename)
254 vty_out(vty, " cdr filename %s%s", g_cfg->cdr.filename, VTY_NEWLINE);
255 else
256 vty_out(vty, " no cdr filename%s", VTY_NEWLINE);
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +0100257 if (g_cfg->cdr.trap)
258 vty_out(vty, " cdr trap%s", VTY_NEWLINE);
259 else
260 vty_out(vty, " no cdr trap%s", VTY_NEWLINE);
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +0200261 vty_out(vty, " cdr interval %d%s", g_cfg->cdr.interval, VTY_NEWLINE);
262
Pau Espin Pedrola299d652019-08-14 19:11:10 +0200263 osmo_tdef_vty_write(vty, g_cfg->T_defs, " timer ");
Harald Welte94508822015-08-15 19:08:21 +0200264
Philippf1f34362016-08-26 17:00:21 +0200265 if (g_cfg->pcomp_rfc1144.active) {
266 vty_out(vty, " compression rfc1144 active slots %d%s",
267 g_cfg->pcomp_rfc1144.s01 + 1, VTY_NEWLINE);
268 } else if (g_cfg->pcomp_rfc1144.passive) {
269 vty_out(vty, " compression rfc1144 passive%s", VTY_NEWLINE);
270 } else
271 vty_out(vty, " no compression rfc1144%s", VTY_NEWLINE);
272
Philipp73f83d52016-09-02 13:38:01 +0200273 if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 1) {
274 vty_out(vty,
275 " compression v42bis active direction sgsn codewords %d strlen %d%s",
276 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
277 VTY_NEWLINE);
278 } else if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 2) {
279 vty_out(vty,
280 " compression v42bis active direction ms codewords %d strlen %d%s",
281 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
282 VTY_NEWLINE);
283 } else if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 3) {
284 vty_out(vty,
285 " compression v42bis active direction both codewords %d strlen %d%s",
286 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
287 VTY_NEWLINE);
288 } else if (g_cfg->dcomp_v42bis.passive) {
289 vty_out(vty, " compression v42bis passive%s", VTY_NEWLINE);
290 } else
291 vty_out(vty, " no compression v42bis%s", VTY_NEWLINE);
292
Neels Hofmeyr2188a772016-05-20 21:59:55 +0200293#ifdef BUILD_IU
Pau Espin Pedrol2c908992019-08-19 19:06:06 +0200294 vty_out(vty, " cs7-instance-iu %u%s", g_cfg->iu.cs7_instance,
295 VTY_NEWLINE);
Neels Hofmeyra7a39472017-07-05 15:19:52 +0200296 ranap_iu_vty_config_write(vty, " ");
Neels Hofmeyr2188a772016-05-20 21:59:55 +0200297#endif
298
Harald Welte288be162010-05-01 16:48:27 +0200299 return CMD_SUCCESS;
300}
301
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100302#define SGSN_STR "Configure the SGSN\n"
303#define GGSN_STR "Configure the GGSN information\n"
Harald Weltee300d002010-06-02 12:41:34 +0200304
305DEFUN(cfg_sgsn, cfg_sgsn_cmd,
306 "sgsn",
307 SGSN_STR)
Harald Welte288be162010-05-01 16:48:27 +0200308{
309 vty->node = SGSN_NODE;
310 return CMD_SUCCESS;
311}
312
Harald Weltee300d002010-06-02 12:41:34 +0200313DEFUN(cfg_sgsn_bind_addr, cfg_sgsn_bind_addr_cmd,
314 "gtp local-ip A.B.C.D",
315 "GTP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100316 "Set the IP address for the local GTP bind for the Gp interface (towards the GGSNs)."
317 " Note: in case you would like to run the GGSN on the same machine as the SGSN, you can not run"
318 " both on the same IP address, since both sides are specified to use the same GTP port numbers"
319 " (" OSMO_STRINGIFY_VAL(GTP1C_PORT) " and " OSMO_STRINGIFY_VAL(GTP1U_PORT) ")."
320 " For example, you could use 127.0.0.1 for the SGSN and 127.0.0.2 for the GGSN in such"
321 " situations.\n"
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100322 "IPv4 Address\n")
Harald Weltee300d002010-06-02 12:41:34 +0200323{
324 inet_aton(argv[0], &g_cfg->gtp_listenaddr.sin_addr);
325
326 return CMD_SUCCESS;
327}
328
Harald Welted193cb32010-05-17 22:58:03 +0200329DEFUN(cfg_ggsn_remote_ip, cfg_ggsn_remote_ip_cmd,
330 "ggsn <0-255> remote-ip A.B.C.D",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100331 GGSN_STR "GGSN Number\n"
332 "Configure this static GGSN to use the specified remote IP address.\n"
333 "IPv4 Address\n")
Harald Welted193cb32010-05-17 22:58:03 +0200334{
335 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200336 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welte288be162010-05-01 16:48:27 +0200337
Harald Welted193cb32010-05-17 22:58:03 +0200338 inet_aton(argv[1], &ggc->remote_addr);
Harald Welte288be162010-05-01 16:48:27 +0200339
Harald Welted193cb32010-05-17 22:58:03 +0200340 return CMD_SUCCESS;
341}
342
343#if 0
344DEFUN(cfg_ggsn_remote_port, cfg_ggsn_remote_port_cmd,
345 "ggsn <0-255> remote-port <0-65535>",
346 "")
347{
348 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200349 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welted193cb32010-05-17 22:58:03 +0200350 uint16_t port = atoi(argv[1]);
351
352}
353#endif
354
355DEFUN(cfg_ggsn_gtp_version, cfg_ggsn_gtp_version_cmd,
356 "ggsn <0-255> gtp-version (0|1)",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100357 GGSN_STR "GGSN Number\n" "GTP Version\n"
358 "Version 0\n" "Version 1\n")
Harald Welted193cb32010-05-17 22:58:03 +0200359{
360 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200361 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welted193cb32010-05-17 22:58:03 +0200362
363 if (atoi(argv[1]))
364 ggc->gtp_version = 1;
365 else
366 ggc->gtp_version = 0;
367
368 return CMD_SUCCESS;
369}
370
Pau Espin Pedrolfa120102018-07-09 20:37:47 +0200371/* Seee 3GPP TS 29.060 section 7.2.1 */
372DEFUN(cfg_ggsn_echo_interval, cfg_ggsn_echo_interval_cmd,
373 "ggsn <0-255> echo-interval <1-36000>",
374 GGSN_STR "GGSN Number\n"
375 "Send an echo request to this static GGSN every interval.\n"
376 "Interval between echo requests in seconds.\n")
377{
378 uint32_t id = atoi(argv[0]);
379 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
380
381 ggc->echo_interval = atoi(argv[1]);
382
383 if (ggc->echo_interval < 60)
Pau Espin Pedrolba2e5002019-05-27 17:35:32 +0200384 vty_out(vty, "%% 3GPP TS 29.060 section 7.2.1 states interval should " \
Pau Espin Pedrolfa120102018-07-09 20:37:47 +0200385 "not be lower than 60 seconds, use this value for " \
386 "testing purposes only!%s", VTY_NEWLINE);
387
Alexander Couzens176a4d22018-09-18 20:07:37 +0200388 sgsn_ggsn_ctx_check_echo_timer(ggc);
Pau Espin Pedrolfa120102018-07-09 20:37:47 +0200389 return CMD_SUCCESS;
390}
391
Pau Espin Pedrola83850c2018-07-10 12:43:59 +0200392DEFUN(cfg_ggsn_no_echo_interval, cfg_ggsn_no_echo_interval_cmd,
393 "ggsn <0-255> no echo-interval",
394 GGSN_STR "GGSN Number\n"
395 NO_STR "Send an echo request to this static GGSN every interval.\n")
396{
397 uint32_t id = atoi(argv[0]);
398 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
399
Pau Espin Pedrolaa89f5d2019-08-28 16:08:45 +0200400 ggc->echo_interval = 0;
Alexander Couzens176a4d22018-09-18 20:07:37 +0200401 sgsn_ggsn_ctx_check_echo_timer(ggc);
Pau Espin Pedrola83850c2018-07-10 12:43:59 +0200402
403 return CMD_SUCCESS;
404}
405
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800406DEFUN(cfg_ggsn_dynamic_lookup, cfg_ggsn_dynamic_lookup_cmd,
407 "ggsn dynamic",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100408 GGSN_STR
409 "Enable dynamic resolving of GGSNs based on DNS resolving the APN name like in a GRX-style setup."
410 " Changing this setting requires a restart.\n")
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800411{
412 sgsn->cfg.dynamic_lookup = 1;
413 return CMD_SUCCESS;
414}
415
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800416DEFUN(cfg_grx_ggsn, cfg_grx_ggsn_cmd,
417 "grx-dns-add A.B.C.D",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100418 "Use the specified IP address for DNS-resolving the AP names to GGSN IP addresses\n"
419 "IPv4 address\n")
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800420{
Pau Espin Pedrolb1d1c242018-10-30 17:27:59 +0100421 struct ares_addr_node *node = talloc_zero(tall_sgsn_ctx, struct ares_addr_node);
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800422 node->family = AF_INET;
423 inet_aton(argv[0], &node->addr.addr4);
424
425 node->next = sgsn->ares_servers;
426 sgsn->ares_servers = node;
427 return CMD_SUCCESS;
428}
429
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100430#define APN_STR "Configure the information per APN\n"
431#define APN_GW_STR "The APN gateway name optionally prefixed by '*' (wildcard)\n"
432
433static int add_apn_ggsn_mapping(struct vty *vty, const char *apn_str,
434 const char *imsi_prefix, int ggsn_id)
435{
436 struct apn_ctx *actx;
437 struct sgsn_ggsn_ctx *ggsn;
438
439 ggsn = sgsn_ggsn_ctx_by_id(ggsn_id);
440 if (ggsn == NULL) {
441 vty_out(vty, "%% a GGSN with id %d has not been defined%s",
442 ggsn_id, VTY_NEWLINE);
443 return CMD_WARNING;
444 }
445
446 actx = sgsn_apn_ctx_find_alloc(apn_str, imsi_prefix);
447 if (!actx) {
448 vty_out(vty, "%% unable to create APN context for %s/%s%s",
449 apn_str, imsi_prefix, VTY_NEWLINE);
450 return CMD_WARNING;
451 }
452
453 actx->ggsn = ggsn;
454
455 return CMD_SUCCESS;
456}
457
Harald Welted193cb32010-05-17 22:58:03 +0200458DEFUN(cfg_apn_ggsn, cfg_apn_ggsn_cmd,
459 "apn APNAME ggsn <0-255>",
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100460 APN_STR APN_GW_STR
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100461 "Select the GGSN to use for the given APN gateway prefix\n"
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100462 "The GGSN id")
Harald Welted193cb32010-05-17 22:58:03 +0200463{
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100464
465 return add_apn_ggsn_mapping(vty, argv[0], "", atoi(argv[1]));
Harald Welted193cb32010-05-17 22:58:03 +0200466}
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100467
468DEFUN(cfg_apn_imsi_ggsn, cfg_apn_imsi_ggsn_cmd,
469 "apn APNAME imsi-prefix IMSIPRE ggsn <0-255>",
470 APN_STR APN_GW_STR
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100471 "Select the GGSN to use for the given APN gateway prefix if and only if the IMSI matches the"
472 " given prefix.\n"
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100473 "An IMSI prefix\n"
474 "Select the GGSN to use when APN gateway and IMSI prefix match\n"
475 "The GGSN id")
476{
477
478 return add_apn_ggsn_mapping(vty, argv[0], argv[1], atoi(argv[2]));
479}
Harald Welted193cb32010-05-17 22:58:03 +0200480
Maxc005db72017-10-27 18:43:29 +0200481char *sgsn_gtp_ntoa(struct ul16_t *ul)
Harald Welte471ac7d2016-12-15 19:48:58 +0100482{
Max8492c202017-12-05 17:28:15 +0100483 struct in_addr ia;
484
485 if (gsna2in_addr(&ia, ul) != 0)
Harald Welte471ac7d2016-12-15 19:48:58 +0100486 return "UNKNOWN";
Max8492c202017-12-05 17:28:15 +0100487
488 return inet_ntoa(ia);
Harald Welte471ac7d2016-12-15 19:48:58 +0100489}
490
Harald Welted193cb32010-05-17 22:58:03 +0200491static void vty_dump_pdp(struct vty *vty, const char *pfx,
492 struct sgsn_pdp_ctx *pdp)
493{
Jacob Erlbeck99985b52014-10-13 10:32:00 +0200494 const char *imsi = pdp->mm ? pdp->mm->imsi : "(detaching)";
Harald Welte471ac7d2016-12-15 19:48:58 +0100495 vty_out(vty, "%sPDP Context IMSI: %s, SAPI: %u, NSAPI: %u, TI: %u%s",
496 pfx, imsi, pdp->sapi, pdp->nsapi, pdp->ti, VTY_NEWLINE);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200497 if (pdp->lib) {
Max7933d962017-10-19 16:52:30 +0200498 char apnbuf[APN_MAXLEN + 1];
Harald Weltedfbd2c82017-08-13 00:56:45 +0200499 vty_out(vty, "%s APN: %s%s", pfx,
Max7933d962017-10-19 16:52:30 +0200500 osmo_apn_to_str(apnbuf, pdp->lib->apn_use.v, pdp->lib->apn_use.l),
Harald Weltedfbd2c82017-08-13 00:56:45 +0200501 VTY_NEWLINE);
502 vty_out(vty, "%s PDP Address: %s%s", pfx,
503 gprs_pdpaddr2str(pdp->lib->eua.v, pdp->lib->eua.l),
504 VTY_NEWLINE);
Maxb24af2b2017-12-05 17:54:42 +0100505 vty_out(vty, "%s GTPv%d Local Control(%s / TEIC: 0x%08x) ", pfx, pdp->lib->version,
Maxc005db72017-10-27 18:43:29 +0200506 sgsn_gtp_ntoa(&pdp->lib->gsnlc), pdp->lib->teic_own);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200507 vty_out(vty, "Data(%s / TEID: 0x%08x)%s",
Maxc005db72017-10-27 18:43:29 +0200508 sgsn_gtp_ntoa(&pdp->lib->gsnlu), pdp->lib->teid_own, VTY_NEWLINE);
Maxb24af2b2017-12-05 17:54:42 +0100509 vty_out(vty, "%s GTPv%d Remote Control(%s / TEIC: 0x%08x) ", pfx, pdp->lib->version,
Maxc005db72017-10-27 18:43:29 +0200510 sgsn_gtp_ntoa(&pdp->lib->gsnrc), pdp->lib->teic_gn);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200511 vty_out(vty, "Data(%s / TEID: 0x%08x)%s",
Maxc005db72017-10-27 18:43:29 +0200512 sgsn_gtp_ntoa(&pdp->lib->gsnru), pdp->lib->teid_gn, VTY_NEWLINE);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200513 }
Harald Welte471ac7d2016-12-15 19:48:58 +0100514
Harald Welteefbdee92010-06-10 00:20:12 +0200515 vty_out_rate_ctr_group(vty, " ", pdp->ctrg);
Harald Welted193cb32010-05-17 22:58:03 +0200516}
517
518static void vty_dump_mmctx(struct vty *vty, const char *pfx,
519 struct sgsn_mm_ctx *mm, int pdp)
520{
Pau Espin Pedrol9119d502019-08-30 17:48:10 +0200521 uint32_t id = 0;
Pau Espin Pedrolfd815bb2019-08-30 18:32:42 +0200522 const char *mm_state_name = NULL;
Pau Espin Pedrol9119d502019-08-30 17:48:10 +0200523
524 switch(mm->ran_type) {
525 case MM_CTX_T_UTRAN_Iu:
526#if BUILD_IU
527 id = mm->iu.ue_ctx->conn_id;
Pau Espin Pedrolfd815bb2019-08-30 18:32:42 +0200528 mm_state_name = osmo_fsm_inst_state_name(mm->iu.mm_state_fsm);
Pau Espin Pedrol9119d502019-08-30 17:48:10 +0200529#endif
530 break;
531 case MM_CTX_T_GERAN_Gb:
532 id = mm->gb.tlli;
Pau Espin Pedrolfd815bb2019-08-30 18:32:42 +0200533 mm_state_name = osmo_fsm_inst_state_name(mm->gb.mm_state_fsm);
Pau Espin Pedrol9119d502019-08-30 17:48:10 +0200534 break;
535 }
536
Harald Welted193cb32010-05-17 22:58:03 +0200537 vty_out(vty, "%sMM Context for IMSI %s, IMEI %s, P-TMSI %08x%s",
538 pfx, mm->imsi, mm->imei, mm->p_tmsi, VTY_NEWLINE);
Holger Hans Peter Freyther8ee13e22015-05-18 10:00:03 +0200539 vty_out(vty, "%s MSISDN: %s, TLLI: %08x%s HLR: %s",
Pau Espin Pedrol9119d502019-08-30 17:48:10 +0200540 pfx, mm->msisdn, id, mm->hlr, VTY_NEWLINE);
Pau Espin Pedrolfd815bb2019-08-30 18:32:42 +0200541 vty_out(vty, "%s GMM State: %s, Routeing Area: %s, Cell ID: %u%s",
Pau Espin Pedrol31c46572019-09-02 16:45:27 +0200542 pfx, osmo_fsm_inst_state_name(mm->gmm_fsm),
Neels Hofmeyr10719b72018-02-21 00:39:36 +0100543 osmo_rai_name(&mm->ra), mm->gb.cell_id, VTY_NEWLINE);
Pau Espin Pedrolfd815bb2019-08-30 18:32:42 +0200544 vty_out(vty, "%s MM State: %s, RAN Type: %s%s", pfx, mm_state_name,
545 get_value_string(sgsn_ran_type_names, mm->ran_type), VTY_NEWLINE);
Harald Welted193cb32010-05-17 22:58:03 +0200546
Pau Espin Pedrol3b848bd2019-08-30 18:06:35 +0200547 vty_out_rate_ctr_group(vty, " ", mm->ctrg);
Harald Welte8acd88f2010-05-18 10:57:45 +0200548
Harald Welted193cb32010-05-17 22:58:03 +0200549 if (pdp) {
550 struct sgsn_pdp_ctx *pdp;
551
552 llist_for_each_entry(pdp, &mm->pdp_list, list)
553 vty_dump_pdp(vty, " ", pdp);
554 }
555}
556
557DEFUN(show_sgsn, show_sgsn_cmd, "show sgsn",
558 SHOW_STR "Display information about the SGSN")
559{
Jacob Erlbeck80547992014-12-19 19:19:46 +0100560 if (sgsn->gsup_client) {
561 struct ipa_client_conn *link = sgsn->gsup_client->link;
562 vty_out(vty,
563 " Remote authorization: %sconnected to %s:%d via GSUP%s",
564 sgsn->gsup_client->is_connected ? "" : "not ",
565 link->addr, link->port,
566 VTY_NEWLINE);
567 }
Maxbaabc682017-10-20 13:39:57 +0200568 if (sgsn->gsn)
569 vty_out(vty, " GSN: signalling %s, user traffic %s%s",
570 inet_ntoa(sgsn->gsn->gsnc), inet_ntoa(sgsn->gsn->gsnu), VTY_NEWLINE);
571
Harald Welted193cb32010-05-17 22:58:03 +0200572 /* FIXME: statistics */
573 return CMD_SUCCESS;
574}
575
576#define MMCTX_STR "MM Context\n"
577#define INCLUDE_PDP_STR "Include PDP Context Information\n"
578
579#if 0
580DEFUN(show_mmctx_tlli, show_mmctx_tlli_cmd,
581 "show mm-context tlli HEX [pdp]",
582 SHOW_STR MMCTX_STR "Identify by TLLI\n" "TLLI\n" INCLUDE_PDP_STR)
583{
584 uint32_t tlli;
585 struct sgsn_mm_ctx *mm;
586
587 tlli = strtoul(argv[0], NULL, 16);
588 mm = sgsn_mm_ctx_by_tlli(tlli);
589 if (!mm) {
590 vty_out(vty, "No MM context for TLLI %08x%s",
591 tlli, VTY_NEWLINE);
592 return CMD_WARNING;
593 }
594 vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
595 return CMD_SUCCESS;
596}
597#endif
598
599DEFUN(swow_mmctx_imsi, show_mmctx_imsi_cmd,
600 "show mm-context imsi IMSI [pdp]",
601 SHOW_STR MMCTX_STR "Identify by IMSI\n" "IMSI of the MM Context\n"
602 INCLUDE_PDP_STR)
603{
604 struct sgsn_mm_ctx *mm;
605
606 mm = sgsn_mm_ctx_by_imsi(argv[0]);
607 if (!mm) {
608 vty_out(vty, "No MM context for IMSI %s%s",
609 argv[0], VTY_NEWLINE);
610 return CMD_WARNING;
611 }
612 vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
613 return CMD_SUCCESS;
614}
615
616DEFUN(swow_mmctx_all, show_mmctx_all_cmd,
617 "show mm-context all [pdp]",
618 SHOW_STR MMCTX_STR "All MM Contexts\n" INCLUDE_PDP_STR)
619{
620 struct sgsn_mm_ctx *mm;
621
622 llist_for_each_entry(mm, &sgsn_mm_ctxts, list)
623 vty_dump_mmctx(vty, "", mm, argv[0] ? 1 : 0);
624
625 return CMD_SUCCESS;
626}
627
Harald Welted193cb32010-05-17 22:58:03 +0200628DEFUN(show_pdpctx_all, show_pdpctx_all_cmd,
629 "show pdp-context all",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100630 SHOW_STR "Display information on PDP Context\n" "Show everything\n")
Harald Welted193cb32010-05-17 22:58:03 +0200631{
632 struct sgsn_pdp_ctx *pdp;
633
634 llist_for_each_entry(pdp, &sgsn_pdp_ctxts, g_list)
635 vty_dump_pdp(vty, "", pdp);
636
637 return CMD_SUCCESS;
638}
Harald Welte288be162010-05-01 16:48:27 +0200639
Harald Welte7f6da482013-03-19 11:00:13 +0100640
641DEFUN(imsi_acl, cfg_imsi_acl_cmd,
642 "imsi-acl (add|del) IMSI",
643 "Access Control List of foreign IMSIs\n"
644 "Add IMSI to ACL\n"
645 "Remove IMSI from ACL\n"
646 "IMSI of subscriber\n")
647{
Maxef38b4c2018-11-20 10:25:53 +0100648 char imsi_sanitized[GSM23003_IMSI_MAX_DIGITS + 1];
Harald Welte7f6da482013-03-19 11:00:13 +0100649 const char *op = argv[0];
Philipp Maier6ee49d82017-02-28 16:53:07 +0100650 const char *imsi = imsi_sanitized;
Maxf4fa6952018-01-15 12:12:51 +0100651 size_t len = strnlen(argv[1], GSM23003_IMSI_MAX_DIGITS + 1);
Harald Welte7f6da482013-03-19 11:00:13 +0100652 int rc;
653
Maxef38b4c2018-11-20 10:25:53 +0100654 memset(imsi_sanitized, '0', GSM23003_IMSI_MAX_DIGITS);
655 imsi_sanitized[GSM23003_IMSI_MAX_DIGITS] = '\0';
656
Philipp Maier6ee49d82017-02-28 16:53:07 +0100657 /* Sanitize IMSI */
Maxf4fa6952018-01-15 12:12:51 +0100658 if (len > GSM23003_IMSI_MAX_DIGITS) {
659 vty_out(vty, "%% IMSI (%s) too long (max %u digits) -- ignored!%s",
660 argv[1], GSM23003_IMSI_MAX_DIGITS, VTY_NEWLINE);
Philipp Maier6ee49d82017-02-28 16:53:07 +0100661 return CMD_WARNING;
662 }
Maxf4fa6952018-01-15 12:12:51 +0100663
664 osmo_strlcpy(imsi_sanitized + GSM23003_IMSI_MAX_DIGITS - len, argv[1],
665 sizeof(imsi_sanitized) - (GSM23003_IMSI_MAX_DIGITS - len));
Philipp Maier6ee49d82017-02-28 16:53:07 +0100666
Harald Welte7f6da482013-03-19 11:00:13 +0100667 if (!strcmp(op, "add"))
Jacob Erlbeck3b5d4072014-10-24 15:11:03 +0200668 rc = sgsn_acl_add(imsi, g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +0100669 else
Jacob Erlbeck3b5d4072014-10-24 15:11:03 +0200670 rc = sgsn_acl_del(imsi, g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +0100671
672 if (rc < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100673 vty_out(vty, "%% unable to %s ACL%s", op, VTY_NEWLINE);
Harald Welte7f6da482013-03-19 11:00:13 +0100674 return CMD_WARNING;
675 }
676
677 return CMD_SUCCESS;
678}
679
Max93408ae2016-06-28 14:10:16 +0200680DEFUN(cfg_encrypt, cfg_encrypt_cmd,
681 "encryption (GEA0|GEA1|GEA2|GEA3|GEA4)",
682 "Set encryption algorithm for SGSN\n"
683 "Use GEA0 (no encryption)\n"
684 "Use GEA1\nUse GEA2\nUse GEA3\nUse GEA4\n")
685{
Max93408ae2016-06-28 14:10:16 +0200686 enum gprs_ciph_algo c = get_string_value(gprs_cipher_names, argv[0]);
Max086067f2017-05-02 13:03:28 +0200687 if (c != GPRS_ALGO_GEA0) {
688 if (!gprs_cipher_supported(c)) {
689 vty_out(vty, "%% cipher %s is unsupported in current version%s", argv[0], VTY_NEWLINE);
690 return CMD_WARNING;
691 }
692
693 if (!g_cfg->require_authentication) {
694 vty_out(vty, "%% unable to use encryption %s without authentication: please adjust auth-policy%s",
695 argv[0], VTY_NEWLINE);
696 return CMD_WARNING;
697 }
Max93408ae2016-06-28 14:10:16 +0200698 }
699
700 g_cfg->cipher = c;
701
702 return CMD_SUCCESS;
703}
704
Vadim Yanitskiy794f4462019-05-27 05:39:06 +0700705DEFUN(cfg_authentication, cfg_authentication_cmd,
706 "authentication (optional|required)",
Pau Espin Pedrold1463bc2019-06-13 19:03:25 +0200707 "Whether to enforce MS authentication in GERAN (only with auth-policy remote)\n"
708 "Allow MS to attach via GERAN without authentication (default and only possible value for non-remote auth-policy)\n"
709 "Always require authentication (only available for auth-policy remote, default with that auth-policy)\n")
Vadim Yanitskiy794f4462019-05-27 05:39:06 +0700710{
711 int required = (argv[0][0] == 'r');
712
713 if (vty->type != VTY_FILE) {
714 if (g_cfg->auth_policy != SGSN_AUTH_POLICY_REMOTE && required) {
715 vty_out(vty, "%% Authentication is not possible without HLR, "
716 "consider setting 'auth-policy' to 'remote'%s",
717 VTY_NEWLINE);
718 return CMD_WARNING;
719 }
720 }
721
722 g_cfg->require_authentication = required;
723 return CMD_SUCCESS;
724}
725
Harald Welte3dfb5492013-03-19 11:48:54 +0100726DEFUN(cfg_auth_policy, cfg_auth_policy_cmd,
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100727 "auth-policy (accept-all|closed|acl-only|remote)",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100728 "Configure the Authorization policy of the SGSN. This setting determines which subscribers are"
729 " permitted to register to the network.\n"
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100730 "Accept all IMSIs (DANGEROUS)\n"
731 "Accept only home network subscribers or those in the ACL\n"
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100732 "Accept only subscribers in the ACL\n"
733 "Use remote subscription data only (HLR)\n")
Harald Welte3dfb5492013-03-19 11:48:54 +0100734{
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100735 int val = get_string_value(sgsn_auth_pol_strs, argv[0]);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100736 OSMO_ASSERT(val >= SGSN_AUTH_POLICY_OPEN && val <= SGSN_AUTH_POLICY_REMOTE);
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100737 g_cfg->auth_policy = val;
Jacob Erlbeck771573c2014-12-19 18:08:48 +0100738 g_cfg->require_update_location = (val == SGSN_AUTH_POLICY_REMOTE);
Harald Welte3dfb5492013-03-19 11:48:54 +0100739
740 return CMD_SUCCESS;
741}
742
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100743/* Subscriber */
Neels Hofmeyr396f2e62017-09-04 15:13:25 +0200744#include <osmocom/sgsn/gprs_subscriber.h>
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100745
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100746static void subscr_dump_full_vty(struct vty *vty, struct gprs_subscr *gsub, int pending)
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100747{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100748#if 0
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100749 char expire_time[200];
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100750#endif
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100751 struct gsm_auth_tuple *at;
752 int at_idx;
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100753 struct sgsn_subscriber_pdp_data *pdp;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100754
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100755 vty_out(vty, " Authorized: %d%s",
756 gsub->authorized, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100757 vty_out(vty, " LAC: %d/0x%x%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100758 gsub->lac, gsub->lac, VTY_NEWLINE);
759 vty_out(vty, " IMSI: %s%s", gsub->imsi, VTY_NEWLINE);
760 if (gsub->tmsi != GSM_RESERVED_TMSI)
761 vty_out(vty, " TMSI: %08X%s", gsub->tmsi,
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100762 VTY_NEWLINE);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100763 if (gsub->sgsn_data->msisdn_len > 0)
Holger Hans Peter Freytherf7b38262015-04-23 16:58:33 -0400764 vty_out(vty, " MSISDN (BCD): %s%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100765 osmo_hexdump(gsub->sgsn_data->msisdn,
766 gsub->sgsn_data->msisdn_len),
Holger Hans Peter Freytherf7b38262015-04-23 16:58:33 -0400767 VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100768
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100769 if (strlen(gsub->imei) > 0)
770 vty_out(vty, " IMEI: %s%s", gsub->imei, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100771
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100772 for (at_idx = 0; at_idx < ARRAY_SIZE(gsub->sgsn_data->auth_triplets);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100773 at_idx++) {
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100774 at = &gsub->sgsn_data->auth_triplets[at_idx];
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100775 if (at->key_seq == GSM_KEY_SEQ_INVAL)
776 continue;
777
778 vty_out(vty, " A3A8 tuple (used %d times): ",
779 at->use_count);
Harald Welte89837d42016-05-06 23:28:11 +0200780 vty_out(vty, " CKSN: %d, ",
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100781 at->key_seq);
Harald Welte89837d42016-05-06 23:28:11 +0200782 if (at->vec.auth_types & OSMO_AUTH_TYPE_GSM) {
783 vty_out(vty, "RAND: %s, ",
Max34604c22019-02-13 14:11:29 +0100784 osmo_hexdump_nospc(at->vec.rand,
Harald Welte89837d42016-05-06 23:28:11 +0200785 sizeof(at->vec.rand)));
786 vty_out(vty, "SRES: %s, ",
Max34604c22019-02-13 14:11:29 +0100787 osmo_hexdump_nospc(at->vec.sres,
Harald Welte89837d42016-05-06 23:28:11 +0200788 sizeof(at->vec.sres)));
789 vty_out(vty, "Kc: %s%s",
Max34604c22019-02-13 14:11:29 +0100790 osmo_hexdump_nospc(at->vec.kc,
Harald Welte89837d42016-05-06 23:28:11 +0200791 sizeof(at->vec.kc)), VTY_NEWLINE);
792 }
793 if (at->vec.auth_types & OSMO_AUTH_TYPE_UMTS) {
794 vty_out(vty, " AUTN: %s, ",
795 osmo_hexdump(at->vec.autn,
796 sizeof(at->vec.autn)));
797 vty_out(vty, "RES: %s, ",
Max34604c22019-02-13 14:11:29 +0100798 osmo_hexdump_nospc(at->vec.res, at->vec.res_len));
Harald Welte89837d42016-05-06 23:28:11 +0200799 vty_out(vty, "IK: %s, ",
Max34604c22019-02-13 14:11:29 +0100800 osmo_hexdump_nospc(at->vec.ik, sizeof(at->vec.ik)));
Harald Welte89837d42016-05-06 23:28:11 +0200801 vty_out(vty, "CK: %s, ",
Max34604c22019-02-13 14:11:29 +0100802 osmo_hexdump_nospc(at->vec.ck, sizeof(at->vec.ck)));
Harald Welte89837d42016-05-06 23:28:11 +0200803 }
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100804 }
805
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100806 llist_for_each_entry(pdp, &gsub->sgsn_data->pdp_list, list) {
Max34604c22019-02-13 14:11:29 +0100807 vty_out(vty, " PDP info: Id: %d, Type: 0x%04x, APN: '%s'",
808 pdp->context_id, pdp->pdp_type, pdp->apn_str);
809
810 if (pdp->qos_subscribed_len)
811 vty_out(vty, " QoS: %s", osmo_hexdump(pdp->qos_subscribed, pdp->qos_subscribed_len));
812
813 vty_out(vty, "%s", VTY_NEWLINE);
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100814 }
815
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100816#if 0
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100817 /* print the expiration time of a subscriber */
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100818 if (gsub->expire_lu) {
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100819 strftime(expire_time, sizeof(expire_time),
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100820 "%a, %d %b %Y %T %z", localtime(&gsub->expire_lu));
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100821 expire_time[sizeof(expire_time) - 1] = '\0';
822 vty_out(vty, " Expiration Time: %s%s", expire_time, VTY_NEWLINE);
823 }
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100824#endif
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100825
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100826 if (gsub->flags)
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100827 vty_out(vty, " Flags: %s%s%s%s%s%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100828 gsub->flags & GPRS_SUBSCRIBER_FIRST_CONTACT ?
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100829 "FIRST_CONTACT " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100830 gsub->flags & GPRS_SUBSCRIBER_CANCELLED ?
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100831 "CANCELLED " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100832 gsub->flags & GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING ?
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100833 "UPDATE_LOCATION_PENDING " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100834 gsub->flags & GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING ?
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100835 "AUTH_INFO_PENDING " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100836 gsub->flags & GPRS_SUBSCRIBER_ENABLE_PURGE ?
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100837 "ENABLE_PURGE " : "",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100838 VTY_NEWLINE);
839
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100840 vty_out(vty, " Use count: %u%s", gsub->use_count, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100841}
842
Neels Hofmeyr1a9414b2018-09-24 18:14:29 +0200843#define RESET_SGSN_STATE_STR \
844 "Remove all known subscribers, MM contexts and flush BSSGP queues." \
845 " Useful only when running tests against the SGSN\n"
846
Alexander Couzensc503f0a2018-08-07 17:50:04 +0200847DEFUN_HIDDEN(reset_sgsn_state,
848 reset_sgsn_state_cmd,
849 "reset sgsn state",
Neels Hofmeyr1a9414b2018-09-24 18:14:29 +0200850 RESET_SGSN_STATE_STR RESET_SGSN_STATE_STR RESET_SGSN_STATE_STR)
Alexander Couzensc503f0a2018-08-07 17:50:04 +0200851{
852 struct gprs_subscr *subscr, *tmp_subscr;
853 struct sgsn_mm_ctx *mm, *tmp_mm;
854
855 llist_for_each_entry_safe(mm, tmp_mm, &sgsn_mm_ctxts, list)
856 {
857 gsm0408_gprs_access_cancelled(mm, SGSN_ERROR_CAUSE_NONE);
858 }
859 vty_out(vty, "Cancelled MM Ctx. %s", VTY_NEWLINE);
860
861 llist_for_each_entry_safe(subscr, tmp_subscr, gprs_subscribers, entry) {
862 gprs_subscr_get(subscr);
863 gprs_subscr_cancel(subscr);
864 gprs_subscr_put(subscr);
865 }
866 vty_out(vty, "Removed all gprs subscribers.%s", VTY_NEWLINE);
867
868 bssgp_flush_all_queues();
869 vty_out(vty, "Flushed all BSSGPs queues.%s", VTY_NEWLINE);
870
Alexander Couzens35c34942018-09-17 04:39:14 +0200871 gtp_clear_queues(sgsn->gsn);
Alexander Couzensa66f0f22018-09-18 16:09:18 +0200872 vty_out(vty, "Flushed rx & tx queus towards the GGSN.%s", VTY_NEWLINE);
Alexander Couzens35c34942018-09-17 04:39:14 +0200873
Alexander Couzensc503f0a2018-08-07 17:50:04 +0200874 /* remove all queues to bssgp */
875 return CMD_SUCCESS;
876}
877
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100878DEFUN(show_subscr_cache,
879 show_subscr_cache_cmd,
880 "show subscriber cache",
881 SHOW_STR "Show information about subscribers\n"
882 "Display contents of subscriber cache\n")
883{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100884 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100885
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100886 llist_for_each_entry(subscr, gprs_subscribers, entry) {
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100887 vty_out(vty, " Subscriber:%s", VTY_NEWLINE);
888 subscr_dump_full_vty(vty, subscr, 0);
889 }
890
891 return CMD_SUCCESS;
892}
893
894#define UPDATE_SUBSCR_STR "update-subscriber imsi IMSI "
895#define UPDATE_SUBSCR_HELP "Update subscriber list\n" \
896 "Use the IMSI to select the subscriber\n" \
897 "The IMSI\n"
898
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100899#define UPDATE_SUBSCR_INSERT_HELP "Insert data into the subscriber record\n"
900
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100901DEFUN(update_subscr_insert_auth_triplet, update_subscr_insert_auth_triplet_cmd,
902 UPDATE_SUBSCR_STR "insert auth-triplet <1-5> sres SRES rand RAND kc KC",
903 UPDATE_SUBSCR_HELP
904 UPDATE_SUBSCR_INSERT_HELP
905 "Update authentication triplet\n"
906 "Triplet index\n"
907 "Set SRES value\nSRES value (4 byte) in hex\n"
908 "Set RAND value\nRAND value (16 byte) in hex\n"
909 "Set Kc value\nKc value (8 byte) in hex\n")
910{
911 const char *imsi = argv[0];
912 const int cksn = atoi(argv[1]) - 1;
913 const char *sres_str = argv[2];
914 const char *rand_str = argv[3];
915 const char *kc_str = argv[4];
916 struct gsm_auth_tuple at = {0,};
917
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100918 struct gprs_subscr *subscr;
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100919
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100920 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100921 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100922 vty_out(vty, "%% unable get subscriber record for %s%s",
923 imsi, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100924 return CMD_WARNING;
925 }
926
927 OSMO_ASSERT(subscr->sgsn_data);
928
Harald Welte121e9a42016-04-20 13:13:19 +0200929 if (osmo_hexparse(sres_str, &at.vec.sres[0], sizeof(at.vec.sres)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100930 vty_out(vty, "%% invalid SRES value '%s'%s",
931 sres_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100932 goto failed;
933 }
Harald Welte121e9a42016-04-20 13:13:19 +0200934 if (osmo_hexparse(rand_str, &at.vec.rand[0], sizeof(at.vec.rand)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100935 vty_out(vty, "%% invalid RAND value '%s'%s",
936 rand_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100937 goto failed;
938 }
Harald Welte121e9a42016-04-20 13:13:19 +0200939 if (osmo_hexparse(kc_str, &at.vec.kc[0], sizeof(at.vec.kc)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100940 vty_out(vty, "%% invalid Kc value '%s'%s",
941 kc_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100942 goto failed;
943 }
944 at.key_seq = cksn;
945
946 subscr->sgsn_data->auth_triplets[cksn] = at;
947 subscr->sgsn_data->auth_triplets_updated = 1;
948
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100949 gprs_subscr_put(subscr);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100950
951 return CMD_SUCCESS;
952
953failed:
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100954 gprs_subscr_put(subscr);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100955 return CMD_SUCCESS;
956}
957
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100958DEFUN(update_subscr_cancel, update_subscr_cancel_cmd,
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100959 UPDATE_SUBSCR_STR "cancel (update-procedure|subscription-withdraw)",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100960 UPDATE_SUBSCR_HELP
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100961 "Cancel (remove) subscriber record\n"
962 "The MS moved to another SGSN\n"
963 "The subscription is no longer valid\n")
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100964{
965 const char *imsi = argv[0];
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100966 const char *cancel_type = argv[1];
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100967
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100968 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100969
970 subscr = gprs_subscr_get_by_imsi(imsi);
971 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100972 vty_out(vty, "%% no subscriber record for %s%s",
973 imsi, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100974 return CMD_WARNING;
975 }
976
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100977 if (strcmp(cancel_type, "update-procedure") == 0)
978 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
979 else
980 subscr->sgsn_data->error_cause = GMM_CAUSE_IMPL_DETACHED;
981
Jacob Erlbeck37139e52015-01-23 13:52:55 +0100982 gprs_subscr_cancel(subscr);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100983 gprs_subscr_put(subscr);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100984
985 return CMD_SUCCESS;
986}
987
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100988DEFUN(update_subscr_create, update_subscr_create_cmd,
989 UPDATE_SUBSCR_STR "create",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100990 UPDATE_SUBSCR_HELP
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100991 "Create a subscriber entry\n")
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100992{
993 const char *imsi = argv[0];
994
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100995 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100996
997 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100998 if (subscr) {
999 vty_out(vty, "%% subscriber record already exists for %s%s",
1000 imsi, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001001 return CMD_WARNING;
1002 }
1003
Jacob Erlbeckd9193432015-01-19 14:11:46 +01001004 subscr = gprs_subscr_get_or_create(imsi);
1005 subscr->keep_in_ram = 1;
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001006 gprs_subscr_put(subscr);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001007
1008 return CMD_SUCCESS;
1009}
1010
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001011DEFUN(update_subscr_destroy, update_subscr_destroy_cmd,
1012 UPDATE_SUBSCR_STR "destroy",
1013 UPDATE_SUBSCR_HELP
1014 "Destroy a subscriber entry\n")
1015{
1016 const char *imsi = argv[0];
1017
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001018 struct gprs_subscr *subscr;
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001019
1020 subscr = gprs_subscr_get_by_imsi(imsi);
1021 if (!subscr) {
1022 vty_out(vty, "%% subscriber record does not exist for %s%s",
1023 imsi, VTY_NEWLINE);
1024 return CMD_WARNING;
1025 }
1026
1027 subscr->keep_in_ram = 0;
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +01001028 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001029 gprs_subscr_cancel(subscr);
1030 if (subscr->use_count > 1)
1031 vty_out(vty, "%% subscriber is still in use%s",
1032 VTY_NEWLINE);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001033 gprs_subscr_put(subscr);
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001034
1035 return CMD_SUCCESS;
1036}
1037
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001038#define UL_ERR_STR "system-failure|data-missing|unexpected-data-value|" \
1039 "unknown-subscriber|roaming-not-allowed"
1040
1041#define UL_ERR_HELP \
1042 "Force error code SystemFailure\n" \
1043 "Force error code DataMissing\n" \
1044 "Force error code UnexpectedDataValue\n" \
1045 "Force error code UnknownSubscriber\n" \
1046 "Force error code RoamingNotAllowed\n"
1047
1048DEFUN(update_subscr_update_location_result, update_subscr_update_location_result_cmd,
1049 UPDATE_SUBSCR_STR "update-location-result (ok|" UL_ERR_STR ")",
1050 UPDATE_SUBSCR_HELP
1051 "Complete the update location procedure\n"
1052 "The update location request succeeded\n"
1053 UL_ERR_HELP)
1054{
1055 const char *imsi = argv[0];
1056 const char *ret_code_str = argv[1];
1057
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001058 struct gprs_subscr *subscr;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001059
Jacob Erlbeckd6267d12015-01-19 11:10:04 +01001060 const struct value_string cause_mapping[] = {
1061 { GMM_CAUSE_NET_FAIL, "system-failure" },
1062 { GMM_CAUSE_INV_MAND_INFO, "data-missing" },
1063 { GMM_CAUSE_PROTO_ERR_UNSPEC, "unexpected-data-value" },
1064 { GMM_CAUSE_IMSI_UNKNOWN, "unknown-subscriber" },
1065 { GMM_CAUSE_GPRS_NOTALLOWED, "roaming-not-allowed" },
1066 { 0, NULL }
1067 };
1068
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001069 subscr = gprs_subscr_get_by_imsi(imsi);
1070 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +01001071 vty_out(vty, "%% unable to get subscriber record for %s%s",
1072 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001073 return CMD_WARNING;
1074 }
Jacob Erlbeckd6267d12015-01-19 11:10:04 +01001075
1076 if (strcmp(ret_code_str, "ok") == 0) {
1077 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001078 subscr->authorized = 1;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +01001079 } else {
1080 subscr->sgsn_data->error_cause =
1081 get_string_value(cause_mapping, ret_code_str);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001082 subscr->authorized = 0;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +01001083 }
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001084
1085 gprs_subscr_update(subscr);
1086
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001087 gprs_subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001088
1089 return CMD_SUCCESS;
1090}
1091
1092DEFUN(update_subscr_update_auth_info, update_subscr_update_auth_info_cmd,
1093 UPDATE_SUBSCR_STR "update-auth-info",
1094 UPDATE_SUBSCR_HELP
1095 "Complete the send authentication info procedure\n")
1096{
1097 const char *imsi = argv[0];
1098
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001099 struct gprs_subscr *subscr;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001100
1101 subscr = gprs_subscr_get_by_imsi(imsi);
1102 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +01001103 vty_out(vty, "%% unable to get subscriber record for %s%s",
1104 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001105 return CMD_WARNING;
1106 }
1107
1108 gprs_subscr_update_auth_info(subscr);
1109
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001110 gprs_subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001111
1112 return CMD_SUCCESS;
1113}
1114
Stefan Sperling88220092018-12-11 14:42:00 +01001115DEFUN(cfg_gsup_ipa_name,
1116 cfg_gsup_ipa_name_cmd,
1117 "gsup ipa-name NAME",
1118 "GSUP Parameters\n"
1119 "Set the IPA name of this SGSN\n"
1120 "A unique name for this SGSN. For example: PLMN + redundancy server number: SGSN-901-70-0. "
1121 "This name is used for GSUP routing and must be set if more than one SGSN is connected to the network. "
1122 "The default is 'SGSN-00-00-00-00-00-00'.\n")
1123{
1124 if (vty->type != VTY_FILE) {
1125 vty_out(vty, "The IPA name cannot be changed at run-time; "
1126 "It can only be set in the configuraton file.%s", VTY_NEWLINE);
1127 return CMD_WARNING;
1128 }
1129
1130 g_cfg->sgsn_ipa_name = talloc_strdup(tall_vty_ctx, argv[0]);
1131 return CMD_SUCCESS;
1132}
1133
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001134DEFUN(cfg_gsup_remote_ip, cfg_gsup_remote_ip_cmd,
1135 "gsup remote-ip A.B.C.D",
1136 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001137 "Set the IP address of the remote GSUP server (e.g. OsmoHLR)."
1138 " This setting only applies if 'auth-policy remote' is used.\n"
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001139 "IPv4 Address\n")
1140{
1141 inet_aton(argv[0], &g_cfg->gsup_server_addr.sin_addr);
1142
1143 return CMD_SUCCESS;
1144}
1145
1146DEFUN(cfg_gsup_remote_port, cfg_gsup_remote_port_cmd,
1147 "gsup remote-port <0-65535>",
1148 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001149 "Set the TCP port of the remote GSUP server, see also 'gsup remote-ip'\n"
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001150 "Remote TCP port\n")
1151{
1152 g_cfg->gsup_server_port = atoi(argv[0]);
1153
1154 return CMD_SUCCESS;
1155}
1156
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001157DEFUN(cfg_gsup_oap_id, cfg_gsup_oap_id_cmd,
1158 "gsup oap-id <0-65535>",
1159 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001160 "Set the OAP client ID for authentication on the GSUP protocol."
1161 " This setting only applies if 'auth-policy remote' is used.\n"
1162 "OAP client ID (0 == disabled)\n")
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001163{
1164 /* VTY ensures range */
1165 g_cfg->oap.client_id = (uint16_t)atoi(argv[0]);
1166 return CMD_SUCCESS;
1167}
1168
1169DEFUN(cfg_gsup_oap_k, cfg_gsup_oap_k_cmd,
1170 "gsup oap-k K",
1171 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001172 "Set the OAP shared secret key K for authentication on the GSUP protocol."
1173 " This setting only applies if auth-policy remote is used.\n"
1174 "K value (16 byte) hex\n")
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001175{
1176 const char *k = argv[0];
1177
1178 g_cfg->oap.secret_k_present = 0;
1179
1180 if ((!k) || (strlen(k) == 0))
1181 goto disable;
1182
1183 int k_len = osmo_hexparse(k,
1184 g_cfg->oap.secret_k,
1185 sizeof(g_cfg->oap.secret_k));
1186 if (k_len != 16) {
1187 vty_out(vty, "%% need exactly 16 octets for oap-k, got %d.%s",
1188 k_len, VTY_NEWLINE);
1189 goto disable;
1190 }
1191
1192 g_cfg->oap.secret_k_present = 1;
1193 return CMD_SUCCESS;
1194
1195disable:
1196 if (g_cfg->oap.client_id > 0) {
1197 vty_out(vty, "%% OAP client ID set, but invalid oap-k value disables OAP.%s",
1198 VTY_NEWLINE);
1199 return CMD_WARNING;
1200 }
1201 return CMD_SUCCESS;
1202}
1203
1204DEFUN(cfg_gsup_oap_opc, cfg_gsup_oap_opc_cmd,
1205 "gsup oap-opc OPC",
1206 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001207 "Set the OAP shared secret OPC for authentication on the GSUP protocol."
1208 " This setting only applies if auth-policy remote is used.\n"
1209 "OPC value (16 byte) hex\n")
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001210{
1211 const char *opc = argv[0];
1212
1213 g_cfg->oap.secret_opc_present = 0;
1214
1215 if ((!opc) || (strlen(opc) == 0))
1216 goto disable;
1217
1218 int opc_len = osmo_hexparse(opc,
1219 g_cfg->oap.secret_opc,
1220 sizeof(g_cfg->oap.secret_opc));
1221 if (opc_len != 16) {
1222 vty_out(vty, "%% need exactly 16 octets for oap-opc, got %d.%s",
1223 opc_len, VTY_NEWLINE);
1224 goto disable;
1225 }
1226
1227 g_cfg->oap.secret_opc_present = 1;
1228 return CMD_SUCCESS;
1229
1230disable:
1231 if (g_cfg->oap.client_id > 0) {
1232 vty_out(vty, "%% OAP client ID set, but invalid oap-opc value disables OAP.%s",
1233 VTY_NEWLINE);
1234 return CMD_WARNING;
1235 }
1236 return CMD_SUCCESS;
1237}
1238
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001239DEFUN(cfg_apn_name, cfg_apn_name_cmd,
1240 "access-point-name NAME",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001241 "Globally allow the given APN name for all subscribers.\n"
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001242 "Add this NAME to the list\n")
1243{
1244 return add_apn_ggsn_mapping(vty, argv[0], "", 0);
1245}
1246
1247DEFUN(cfg_no_apn_name, cfg_no_apn_name_cmd,
1248 "no access-point-name NAME",
1249 NO_STR "Configure a global list of allowed APNs\n"
1250 "Remove entry with NAME\n")
1251{
1252 struct apn_ctx *apn_ctx = sgsn_apn_ctx_by_name(argv[0], "");
1253 if (!apn_ctx)
1254 return CMD_SUCCESS;
1255
1256 sgsn_apn_ctx_free(apn_ctx);
1257 return CMD_SUCCESS;
1258}
1259
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001260DEFUN(cfg_cdr_filename, cfg_cdr_filename_cmd,
1261 "cdr filename NAME",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001262 "CDR\n"
1263 "Set the file name for the call-data-record file, logging the data usage of each subscriber.\n"
1264 "filename\n")
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001265{
1266 talloc_free(g_cfg->cdr.filename);
1267 g_cfg->cdr.filename = talloc_strdup(tall_vty_ctx, argv[0]);
1268 return CMD_SUCCESS;
1269}
1270
1271DEFUN(cfg_no_cdr_filename, cfg_no_cdr_filename_cmd,
1272 "no cdr filename",
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +01001273 NO_STR "CDR\nDisable saving CDR to file\n")
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001274{
1275 talloc_free(g_cfg->cdr.filename);
1276 g_cfg->cdr.filename = NULL;
1277 return CMD_SUCCESS;
1278}
1279
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +01001280DEFUN(cfg_cdr_trap, cfg_cdr_trap_cmd,
1281 "cdr trap",
1282 "CDR\nEnable sending CDR via TRAP CTRL messages\n")
1283{
1284 g_cfg->cdr.trap = true;
1285 return CMD_SUCCESS;
1286}
1287
1288DEFUN(cfg_no_cdr_trap, cfg_no_cdr_trap_cmd,
1289 "no cdr trap",
1290 NO_STR "CDR\nDisable sending CDR via TRAP CTRL messages\n")
1291{
1292 g_cfg->cdr.trap = false;
1293 return CMD_SUCCESS;
1294}
1295
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001296DEFUN(cfg_cdr_interval, cfg_cdr_interval_cmd,
1297 "cdr interval <1-2147483647>",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001298 "CDR\n"
1299 "Set the interval for the call-data-record file\n"
1300 "interval in seconds\n")
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001301{
1302 g_cfg->cdr.interval = atoi(argv[0]);
1303 return CMD_SUCCESS;
1304}
1305
Philippf1f34362016-08-26 17:00:21 +02001306#define COMPRESSION_STR "Configure compression\n"
1307DEFUN(cfg_no_comp_rfc1144, cfg_no_comp_rfc1144_cmd,
1308 "no compression rfc1144",
1309 NO_STR COMPRESSION_STR "disable rfc1144 TCP/IP header compression\n")
1310{
1311 g_cfg->pcomp_rfc1144.active = 0;
1312 g_cfg->pcomp_rfc1144.passive = 0;
1313 return CMD_SUCCESS;
1314}
1315
1316DEFUN(cfg_comp_rfc1144, cfg_comp_rfc1144_cmd,
1317 "compression rfc1144 active slots <1-256>",
1318 COMPRESSION_STR
Ruben Undheim55fcf112018-09-25 22:59:34 +02001319 "RFC1144 Header compression scheme\n"
Philippf1f34362016-08-26 17:00:21 +02001320 "Compression is actively proposed\n"
1321 "Number of compression state slots\n"
1322 "Number of compression state slots\n")
1323{
1324 g_cfg->pcomp_rfc1144.active = 1;
1325 g_cfg->pcomp_rfc1144.passive = 1;
1326 g_cfg->pcomp_rfc1144.s01 = atoi(argv[0]) - 1;
1327 return CMD_SUCCESS;
1328}
1329
1330DEFUN(cfg_comp_rfc1144p, cfg_comp_rfc1144p_cmd,
1331 "compression rfc1144 passive",
1332 COMPRESSION_STR
Ruben Undheim55fcf112018-09-25 22:59:34 +02001333 "RFC1144 Header compression scheme\n"
Philippf1f34362016-08-26 17:00:21 +02001334 "Compression is available on request\n")
1335{
1336 g_cfg->pcomp_rfc1144.active = 0;
1337 g_cfg->pcomp_rfc1144.passive = 1;
1338 return CMD_SUCCESS;
1339}
1340
Philipp73f83d52016-09-02 13:38:01 +02001341DEFUN(cfg_no_comp_v42bis, cfg_no_comp_v42bis_cmd,
1342 "no compression v42bis",
1343 NO_STR COMPRESSION_STR "disable V.42bis data compression\n")
1344{
1345 g_cfg->dcomp_v42bis.active = 0;
1346 g_cfg->dcomp_v42bis.passive = 0;
1347 return CMD_SUCCESS;
1348}
1349
1350DEFUN(cfg_comp_v42bis, cfg_comp_v42bis_cmd,
1351 "compression v42bis active direction (ms|sgsn|both) codewords <512-65535> strlen <6-250>",
1352 COMPRESSION_STR
Ruben Undheim55fcf112018-09-25 22:59:34 +02001353 "V.42bis data compression scheme\n"
Philipp73f83d52016-09-02 13:38:01 +02001354 "Compression is actively proposed\n"
1355 "Direction in which the compression shall be active (p0)\n"
1356 "Compress ms->sgsn direction only\n"
1357 "Compress sgsn->ms direction only\n"
1358 "Both directions\n"
1359 "Number of codewords (p1)\n"
1360 "Number of codewords\n"
1361 "Maximum string length (p2)\n" "Maximum string length\n")
1362{
1363 g_cfg->dcomp_v42bis.active = 1;
1364 g_cfg->dcomp_v42bis.passive = 1;
1365
1366 switch (argv[0][0]) {
1367 case 'm':
1368 g_cfg->dcomp_v42bis.p0 = 1;
1369 break;
1370 case 's':
1371 g_cfg->dcomp_v42bis.p0 = 2;
1372 break;
1373 case 'b':
1374 g_cfg->dcomp_v42bis.p0 = 3;
1375 break;
1376 }
1377
1378 g_cfg->dcomp_v42bis.p1 = atoi(argv[1]);
1379 g_cfg->dcomp_v42bis.p2 = atoi(argv[2]);
1380 return CMD_SUCCESS;
1381}
1382
1383DEFUN(cfg_comp_v42bisp, cfg_comp_v42bisp_cmd,
1384 "compression v42bis passive",
1385 COMPRESSION_STR
Ruben Undheim55fcf112018-09-25 22:59:34 +02001386 "V.42bis data compression scheme\n"
Philipp73f83d52016-09-02 13:38:01 +02001387 "Compression is available on request\n")
1388{
1389 g_cfg->dcomp_v42bis.active = 0;
1390 g_cfg->dcomp_v42bis.passive = 1;
1391 return CMD_SUCCESS;
1392}
1393
Pau Espin Pedrol2c908992019-08-19 19:06:06 +02001394#if BUILD_IU
1395DEFUN(cfg_sgsn_cs7_instance_iu,
1396 cfg_sgsn_cs7_instance_iu_cmd,
1397 "cs7-instance-iu <0-15>",
1398 "Set SS7 to be used by the Iu-Interface.\n" "SS7 instance reference number (default: 0)\n")
1399{
1400 g_cfg->iu.cs7_instance = atoi(argv[0]);
1401 return CMD_SUCCESS;
1402}
1403#endif
1404
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001405int sgsn_vty_init(struct sgsn_config *cfg)
Harald Welte288be162010-05-01 16:48:27 +02001406{
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001407 g_cfg = cfg;
1408
Pau Espin Pedrola299d652019-08-14 19:11:10 +02001409 g_cfg->T_defs = sgsn_T_defs;
1410 osmo_tdefs_reset(g_cfg->T_defs);
1411
Harald Welted193cb32010-05-17 22:58:03 +02001412 install_element_ve(&show_sgsn_cmd);
1413 //install_element_ve(&show_mmctx_tlli_cmd);
1414 install_element_ve(&show_mmctx_imsi_cmd);
1415 install_element_ve(&show_mmctx_all_cmd);
1416 install_element_ve(&show_pdpctx_all_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001417 install_element_ve(&show_subscr_cache_cmd);
Pau Espin Pedrola299d652019-08-14 19:11:10 +02001418 install_element_ve(&show_timer_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001419
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01001420 install_element(ENABLE_NODE, &update_subscr_insert_auth_triplet_cmd);
Jacob Erlbeckd9193432015-01-19 14:11:46 +01001421 install_element(ENABLE_NODE, &update_subscr_create_cmd);
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001422 install_element(ENABLE_NODE, &update_subscr_destroy_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001423 install_element(ENABLE_NODE, &update_subscr_cancel_cmd);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001424 install_element(ENABLE_NODE, &update_subscr_update_location_result_cmd);
1425 install_element(ENABLE_NODE, &update_subscr_update_auth_info_cmd);
Alexander Couzensc503f0a2018-08-07 17:50:04 +02001426 install_element(ENABLE_NODE, &reset_sgsn_state_cmd);
Harald Welte288be162010-05-01 16:48:27 +02001427
1428 install_element(CONFIG_NODE, &cfg_sgsn_cmd);
1429 install_node(&sgsn_node, config_write_sgsn);
Harald Weltee300d002010-06-02 12:41:34 +02001430 install_element(SGSN_NODE, &cfg_sgsn_bind_addr_cmd);
Harald Welted193cb32010-05-17 22:58:03 +02001431 install_element(SGSN_NODE, &cfg_ggsn_remote_ip_cmd);
1432 //install_element(SGSN_NODE, &cfg_ggsn_remote_port_cmd);
1433 install_element(SGSN_NODE, &cfg_ggsn_gtp_version_cmd);
Pau Espin Pedrolfa120102018-07-09 20:37:47 +02001434 install_element(SGSN_NODE, &cfg_ggsn_echo_interval_cmd);
Pau Espin Pedrola83850c2018-07-10 12:43:59 +02001435 install_element(SGSN_NODE, &cfg_ggsn_no_echo_interval_cmd);
Harald Welte7f6da482013-03-19 11:00:13 +01001436 install_element(SGSN_NODE, &cfg_imsi_acl_cmd);
Harald Welte3dfb5492013-03-19 11:48:54 +01001437 install_element(SGSN_NODE, &cfg_auth_policy_cmd);
Vadim Yanitskiy794f4462019-05-27 05:39:06 +07001438 install_element(SGSN_NODE, &cfg_authentication_cmd);
Max93408ae2016-06-28 14:10:16 +02001439 install_element(SGSN_NODE, &cfg_encrypt_cmd);
Stefan Sperling88220092018-12-11 14:42:00 +01001440 install_element(SGSN_NODE, &cfg_gsup_ipa_name_cmd);
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001441 install_element(SGSN_NODE, &cfg_gsup_remote_ip_cmd);
1442 install_element(SGSN_NODE, &cfg_gsup_remote_port_cmd);
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001443 install_element(SGSN_NODE, &cfg_gsup_oap_id_cmd);
1444 install_element(SGSN_NODE, &cfg_gsup_oap_k_cmd);
1445 install_element(SGSN_NODE, &cfg_gsup_oap_opc_cmd);
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +01001446 install_element(SGSN_NODE, &cfg_apn_ggsn_cmd);
1447 install_element(SGSN_NODE, &cfg_apn_imsi_ggsn_cmd);
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001448 install_element(SGSN_NODE, &cfg_apn_name_cmd);
1449 install_element(SGSN_NODE, &cfg_no_apn_name_cmd);
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001450 install_element(SGSN_NODE, &cfg_cdr_filename_cmd);
1451 install_element(SGSN_NODE, &cfg_no_cdr_filename_cmd);
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +01001452 install_element(SGSN_NODE, &cfg_cdr_trap_cmd);
1453 install_element(SGSN_NODE, &cfg_no_cdr_trap_cmd);
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001454 install_element(SGSN_NODE, &cfg_cdr_interval_cmd);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001455 install_element(SGSN_NODE, &cfg_ggsn_dynamic_lookup_cmd);
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +08001456 install_element(SGSN_NODE, &cfg_grx_ggsn_cmd);
Harald Welte288be162010-05-01 16:48:27 +02001457
Pau Espin Pedrola299d652019-08-14 19:11:10 +02001458 install_element(SGSN_NODE, &cfg_sgsn_timer_cmd);
Harald Welte94508822015-08-15 19:08:21 +02001459
Philippf1f34362016-08-26 17:00:21 +02001460 install_element(SGSN_NODE, &cfg_no_comp_rfc1144_cmd);
1461 install_element(SGSN_NODE, &cfg_comp_rfc1144_cmd);
1462 install_element(SGSN_NODE, &cfg_comp_rfc1144p_cmd);
Philipp73f83d52016-09-02 13:38:01 +02001463 install_element(SGSN_NODE, &cfg_no_comp_v42bis_cmd);
1464 install_element(SGSN_NODE, &cfg_comp_v42bis_cmd);
1465 install_element(SGSN_NODE, &cfg_comp_v42bisp_cmd);
Neels Hofmeyr2188a772016-05-20 21:59:55 +02001466
1467#ifdef BUILD_IU
Pau Espin Pedrol2c908992019-08-19 19:06:06 +02001468 install_element(SGSN_NODE, &cfg_sgsn_cs7_instance_iu_cmd);
Neels Hofmeyra7a39472017-07-05 15:19:52 +02001469 ranap_iu_vty_init(SGSN_NODE, &g_cfg->iu.rab_assign_addr_enc);
Neels Hofmeyr2188a772016-05-20 21:59:55 +02001470#endif
Harald Welte288be162010-05-01 16:48:27 +02001471 return 0;
1472}
1473
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001474int sgsn_parse_config(const char *config_file)
Harald Welte288be162010-05-01 16:48:27 +02001475{
1476 int rc;
1477
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001478 /* make sure sgsn_vty_init() was called before this */
1479 OSMO_ASSERT(g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +01001480
Harald Weltedcccb182010-05-16 20:52:23 +02001481 rc = vty_read_config_file(config_file, NULL);
Harald Welte288be162010-05-01 16:48:27 +02001482 if (rc < 0) {
1483 fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
1484 return rc;
1485 }
1486
Neels Hofmeyr27355c92017-02-24 06:28:31 +01001487 if (g_cfg->auth_policy == SGSN_AUTH_POLICY_REMOTE
1488 && !(g_cfg->gsup_server_addr.sin_addr.s_addr
1489 && g_cfg->gsup_server_port)) {
1490 fprintf(stderr, "Configuration error:"
1491 " 'auth-policy remote' requires both"
1492 " 'gsup remote-ip' and 'gsup remote-port'\n");
1493 return -EINVAL;
1494 }
1495
Harald Welte288be162010-05-01 16:48:27 +02001496 return 0;
1497}