blob: edc5b09f931b1cca07430da79842cfca1c3b0dc0 [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>
Harald Welte53373bc2016-04-20 17:11:43 +020031#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
Harald Welte7e82b742017-08-12 13:43:54 +020032#include <osmocom/gsm/apn.h>
Harald Welte288be162010-05-01 16:48:27 +020033
Neels Hofmeyr396f2e62017-09-04 15:13:25 +020034#include <osmocom/sgsn/debug.h>
35#include <osmocom/sgsn/sgsn.h>
Harald Welteea34a4e2012-06-16 14:59:56 +080036#include <osmocom/gprs/gprs_ns.h>
Alexander Couzensc503f0a2018-08-07 17:50:04 +020037#include <osmocom/sgsn/gprs_gmm.h>
Neels Hofmeyr396f2e62017-09-04 15:13:25 +020038#include <osmocom/sgsn/gprs_sgsn.h>
39#include <osmocom/sgsn/vty.h>
Harald Weltef4b2c4c2018-09-16 07:53:41 +020040#include <osmocom/gsupclient/gsup_client.h>
Harald Welte288be162010-05-01 16:48:27 +020041
Harald Welte4b037e42010-05-19 19:45:32 +020042#include <osmocom/vty/command.h>
43#include <osmocom/vty/vty.h>
Pablo Neira Ayuso6110a3f2011-03-28 19:35:00 +020044#include <osmocom/vty/misc.h>
Max93408ae2016-06-28 14:10:16 +020045#include <osmocom/crypt/gprs_cipher.h>
Jacob Erlbeck80547992014-12-19 19:19:46 +010046#include <osmocom/abis/ipa.h>
47
Alexander Couzensc503f0a2018-08-07 17:50:04 +020048#include <osmocom/gprs/gprs_bssgp.h>
49
Harald Welted193cb32010-05-17 22:58:03 +020050#include <pdp.h>
Maxbaabc682017-10-20 13:39:57 +020051#include <gtp.h>
Harald Welted193cb32010-05-17 22:58:03 +020052
Neels Hofmeyr2188a772016-05-20 21:59:55 +020053#include "../../bscconfig.h"
54
55#ifdef BUILD_IU
Neels Hofmeyra7a39472017-07-05 15:19:52 +020056#include <osmocom/ranap/iu_client.h>
Neels Hofmeyr2188a772016-05-20 21:59:55 +020057#endif
58
Pau Espin Pedrolb1d1c242018-10-30 17:27:59 +010059extern void *tall_sgsn_ctx;
Neels Hofmeyree6cfdc2017-07-13 02:03:50 +020060
Harald Welte288be162010-05-01 16:48:27 +020061static struct sgsn_config *g_cfg = NULL;
62
Jacob Erlbeck106f5472014-11-04 10:08:37 +010063const struct value_string sgsn_auth_pol_strs[] = {
64 { SGSN_AUTH_POLICY_OPEN, "accept-all" },
65 { SGSN_AUTH_POLICY_CLOSED, "closed" },
66 { SGSN_AUTH_POLICY_ACL_ONLY, "acl-only" },
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +010067 { SGSN_AUTH_POLICY_REMOTE, "remote" },
Jacob Erlbeck106f5472014-11-04 10:08:37 +010068 { 0, NULL }
69};
70
Harald Welte94508822015-08-15 19:08:21 +020071/* Section 11.2.2 / Table 11.3a GPRS Mobility management timers – MS side */
72#define GSM0408_T3312_SECS (10*60) /* periodic RAU interval, default 54min */
73
74/* Section 11.2.2 / Table 11.4 MM timers netwokr side */
75#define GSM0408_T3322_SECS 6 /* DETACH_REQ -> DETACH_ACC */
76#define GSM0408_T3350_SECS 6 /* waiting for ATT/RAU/TMSI COMPL */
77#define GSM0408_T3360_SECS 6 /* waiting for AUTH/CIPH RESP */
78#define GSM0408_T3370_SECS 6 /* waiting for ID RESP */
79
Alexander Couzens5ba6fb32017-01-31 18:04:27 +010080/* Section 11.2.2 / Table 11.4a MM timers network side */
Harald Welte94508822015-08-15 19:08:21 +020081#define GSM0408_T3313_SECS 30 /* waiting for paging response */
82#define GSM0408_T3314_SECS 44 /* force to STBY on expiry, Ready timer */
83#define GSM0408_T3316_SECS 44
84
85/* Section 11.3 / Table 11.2d Timers of Session Management - network side */
86#define GSM0408_T3385_SECS 8 /* wait for ACT PDP CTX REQ */
87#define GSM0408_T3386_SECS 8 /* wait for MODIFY PDP CTX ACK */
88#define GSM0408_T3395_SECS 8 /* wait for DEACT PDP CTX ACK */
89#define GSM0408_T3397_SECS 8 /* wait for DEACT AA PDP CTX ACK */
90
91#define DECLARE_TIMER(number, doc) \
92 DEFUN(cfg_sgsn_T##number, \
93 cfg_sgsn_T##number##_cmd, \
94 "timer t" #number " <0-65535>", \
95 "Configure GPRS Timers\n" \
Holger Hans Peter Freytherfe60cfb2015-11-02 12:55:07 +010096 doc "\nTimer Value in seconds\n") \
Harald Welte94508822015-08-15 19:08:21 +020097{ \
98 int value = atoi(argv[0]); \
99 \
100 if (value < 0 || value > 65535) { \
101 vty_out(vty, "Timer value %s out of range.%s", \
102 argv[0], VTY_NEWLINE); \
103 return CMD_WARNING; \
104 } \
105 \
106 g_cfg->timers.T##number = value; \
107 return CMD_SUCCESS; \
108}
109
110DECLARE_TIMER(3312, "Periodic RA Update timer (s)")
Neels Hofmeyr65482c92015-10-19 14:37:12 +0200111DECLARE_TIMER(3322, "Detach request -> accept timer (s)")
Harald Welte94508822015-08-15 19:08:21 +0200112DECLARE_TIMER(3350, "Waiting for ATT/RAU/TMSI_COMPL timer (s)")
113DECLARE_TIMER(3360, "Waiting for AUTH/CIPH response timer (s)")
114DECLARE_TIMER(3370, "Waiting for IDENTITY response timer (s)")
115
116DECLARE_TIMER(3313, "Waiting for paging response timer (s)")
117DECLARE_TIMER(3314, "Force to STANDBY on expiry timer (s)")
Holger Hans Peter Freytherfe60cfb2015-11-02 12:55:07 +0100118DECLARE_TIMER(3316, "AA-Ready timer (s)")
Harald Welte94508822015-08-15 19:08:21 +0200119
120DECLARE_TIMER(3385, "Wait for ACT PDP CTX REQ timer (s)")
121DECLARE_TIMER(3386, "Wait for MODIFY PDP CTX ACK timer (s)")
122DECLARE_TIMER(3395, "Wait for DEACT PDP CTX ACK timer (s)")
123DECLARE_TIMER(3397, "Wait for DEACT AA PDP CTX ACK timer (s)")
124
Holger Hans Peter Freythera2730302014-03-23 18:08:26 +0100125char *gprs_pdpaddr2str(uint8_t *pdpa, uint8_t len)
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200126{
127 static char str[INET6_ADDRSTRLEN + 10];
128
129 if (!pdpa || len < 2)
130 return "none";
131
132 switch (pdpa[0] & 0x0f) {
133 case PDP_TYPE_ORG_IETF:
134 switch (pdpa[1]) {
135 case PDP_TYPE_N_IETF_IPv4:
136 if (len < 2 + 4)
137 break;
138 strcpy(str, "IPv4 ");
139 inet_ntop(AF_INET, pdpa+2, str+5, sizeof(str)-5);
140 return str;
141 case PDP_TYPE_N_IETF_IPv6:
142 if (len < 2 + 8)
143 break;
144 strcpy(str, "IPv6 ");
145 inet_ntop(AF_INET6, pdpa+2, str+5, sizeof(str)-5);
146 return str;
147 default:
148 break;
149 }
150 break;
151 case PDP_TYPE_ORG_ETSI:
152 if (pdpa[1] == PDP_TYPE_N_ETSI_PPP)
153 return "PPP";
154 break;
155 default:
156 break;
157 }
158
159 return "invalid";
160}
161
Harald Welte288be162010-05-01 16:48:27 +0200162static struct cmd_node sgsn_node = {
163 SGSN_NODE,
Harald Welte570ce242012-08-17 13:16:10 +0200164 "%s(config-sgsn)# ",
Harald Welte288be162010-05-01 16:48:27 +0200165 1,
166};
167
168static int config_write_sgsn(struct vty *vty)
169{
Harald Welte77289c22010-05-18 14:32:29 +0200170 struct sgsn_ggsn_ctx *gctx;
Harald Welte7f6da482013-03-19 11:00:13 +0100171 struct imsi_acl_entry *acl;
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100172 struct apn_ctx *actx;
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800173 struct ares_addr_node *server;
Harald Welte288be162010-05-01 16:48:27 +0200174
175 vty_out(vty, "sgsn%s", VTY_NEWLINE);
176
Harald Weltee300d002010-06-02 12:41:34 +0200177 vty_out(vty, " gtp local-ip %s%s",
178 inet_ntoa(g_cfg->gtp_listenaddr.sin_addr), VTY_NEWLINE);
179
Harald Welted193cb32010-05-17 22:58:03 +0200180 llist_for_each_entry(gctx, &sgsn_ggsn_ctxts, list) {
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800181 if (gctx->id == UINT32_MAX)
182 continue;
183
Harald Welteff3bde82010-05-19 15:09:09 +0200184 vty_out(vty, " ggsn %u remote-ip %s%s", gctx->id,
Harald Welted193cb32010-05-17 22:58:03 +0200185 inet_ntoa(gctx->remote_addr), VTY_NEWLINE);
Harald Welteff3bde82010-05-19 15:09:09 +0200186 vty_out(vty, " ggsn %u gtp-version %u%s", gctx->id,
Harald Welted193cb32010-05-17 22:58:03 +0200187 gctx->gtp_version, VTY_NEWLINE);
Pau Espin Pedrolfa120102018-07-09 20:37:47 +0200188 if (gctx->echo_interval != -1)
189 vty_out(vty, " ggsn %u echo-interval %"PRId32"%s",
190 gctx->id, gctx->echo_interval, VTY_NEWLINE);
Pau Espin Pedrola83850c2018-07-10 12:43:59 +0200191 else
192 vty_out(vty, " ggsn %u no echo-interval%s",
193 gctx->id, VTY_NEWLINE);
Harald Welte288be162010-05-01 16:48:27 +0200194 }
195
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800196 if (sgsn->cfg.dynamic_lookup)
197 vty_out(vty, " ggsn dynamic%s", VTY_NEWLINE);
198
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800199 for (server = sgsn->ares_servers; server; server = server->next)
200 vty_out(vty, " grx-dns-add %s%s", inet_ntoa(server->addr.addr4), VTY_NEWLINE);
201
Max93408ae2016-06-28 14:10:16 +0200202 if (g_cfg->cipher != GPRS_ALGO_GEA0)
203 vty_out(vty, " encryption %s%s",
204 get_value_string(gprs_cipher_names, g_cfg->cipher),
205 VTY_NEWLINE);
Stefan Sperling88220092018-12-11 14:42:00 +0100206 if (g_cfg->sgsn_ipa_name)
207 vty_out(vty, " gsup ipa-name %s%s", g_cfg->sgsn_ipa_name, VTY_NEWLINE);
Jacob Erlbeck39f040d2014-12-18 12:46:47 +0100208 if (g_cfg->gsup_server_addr.sin_addr.s_addr)
209 vty_out(vty, " gsup remote-ip %s%s",
210 inet_ntoa(g_cfg->gsup_server_addr.sin_addr), VTY_NEWLINE);
211 if (g_cfg->gsup_server_port)
212 vty_out(vty, " gsup remote-port %d%s",
213 g_cfg->gsup_server_port, VTY_NEWLINE);
Pau Espin Pedrold1463bc2019-06-13 19:03:25 +0200214 if (g_cfg->auth_policy == SGSN_AUTH_POLICY_REMOTE && !g_cfg->require_authentication)
215 vty_out(vty, " authentication optional%s", VTY_NEWLINE);
Max176b62a2016-07-04 11:09:07 +0200216 vty_out(vty, " auth-policy %s%s",
217 get_value_string(sgsn_auth_pol_strs, g_cfg->auth_policy),
218 VTY_NEWLINE);
Neels Hofmeyr568a7272015-10-12 11:57:38 +0200219
220 vty_out(vty, " gsup oap-id %d%s",
221 (int)g_cfg->oap.client_id, VTY_NEWLINE);
222 if (g_cfg->oap.secret_k_present != 0)
223 vty_out(vty, " gsup oap-k %s%s",
224 osmo_hexdump_nospc(g_cfg->oap.secret_k, sizeof(g_cfg->oap.secret_k)),
225 VTY_NEWLINE);
226 if (g_cfg->oap.secret_opc_present != 0)
227 vty_out(vty, " gsup oap-opc %s%s",
228 osmo_hexdump_nospc(g_cfg->oap.secret_opc, sizeof(g_cfg->oap.secret_opc)),
229 VTY_NEWLINE);
230
Harald Welte7f6da482013-03-19 11:00:13 +0100231 llist_for_each_entry(acl, &g_cfg->imsi_acl, list)
232 vty_out(vty, " imsi-acl add %s%s", acl->imsi, VTY_NEWLINE);
233
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100234 if (llist_empty(&sgsn_apn_ctxts))
235 vty_out(vty, " ! apn * ggsn 0%s", VTY_NEWLINE);
236 llist_for_each_entry(actx, &sgsn_apn_ctxts, list) {
237 if (strlen(actx->imsi_prefix) > 0)
Holger Hans Peter Freytherb7ae0b32015-05-29 15:11:55 +0200238 vty_out(vty, " apn %s imsi-prefix %s ggsn %u%s",
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100239 actx->name, actx->imsi_prefix, actx->ggsn->id,
240 VTY_NEWLINE);
241 else
Holger Hans Peter Freytherb7ae0b32015-05-29 15:11:55 +0200242 vty_out(vty, " apn %s ggsn %u%s", actx->name,
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100243 actx->ggsn->id, VTY_NEWLINE);
244 }
245
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +0200246 if (g_cfg->cdr.filename)
247 vty_out(vty, " cdr filename %s%s", g_cfg->cdr.filename, VTY_NEWLINE);
248 else
249 vty_out(vty, " no cdr filename%s", VTY_NEWLINE);
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +0100250 if (g_cfg->cdr.trap)
251 vty_out(vty, " cdr trap%s", VTY_NEWLINE);
252 else
253 vty_out(vty, " no cdr trap%s", VTY_NEWLINE);
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +0200254 vty_out(vty, " cdr interval %d%s", g_cfg->cdr.interval, VTY_NEWLINE);
255
Harald Welte94508822015-08-15 19:08:21 +0200256 vty_out(vty, " timer t3312 %d%s", g_cfg->timers.T3312, VTY_NEWLINE);
257 vty_out(vty, " timer t3322 %d%s", g_cfg->timers.T3322, VTY_NEWLINE);
258 vty_out(vty, " timer t3350 %d%s", g_cfg->timers.T3350, VTY_NEWLINE);
259 vty_out(vty, " timer t3360 %d%s", g_cfg->timers.T3360, VTY_NEWLINE);
260 vty_out(vty, " timer t3370 %d%s", g_cfg->timers.T3370, VTY_NEWLINE);
261 vty_out(vty, " timer t3313 %d%s", g_cfg->timers.T3313, VTY_NEWLINE);
262 vty_out(vty, " timer t3314 %d%s", g_cfg->timers.T3314, VTY_NEWLINE);
263 vty_out(vty, " timer t3316 %d%s", g_cfg->timers.T3316, VTY_NEWLINE);
264 vty_out(vty, " timer t3385 %d%s", g_cfg->timers.T3385, VTY_NEWLINE);
265 vty_out(vty, " timer t3386 %d%s", g_cfg->timers.T3386, VTY_NEWLINE);
266 vty_out(vty, " timer t3395 %d%s", g_cfg->timers.T3395, VTY_NEWLINE);
267 vty_out(vty, " timer t3397 %d%s", g_cfg->timers.T3397, VTY_NEWLINE);
268
Philippf1f34362016-08-26 17:00:21 +0200269 if (g_cfg->pcomp_rfc1144.active) {
270 vty_out(vty, " compression rfc1144 active slots %d%s",
271 g_cfg->pcomp_rfc1144.s01 + 1, VTY_NEWLINE);
272 } else if (g_cfg->pcomp_rfc1144.passive) {
273 vty_out(vty, " compression rfc1144 passive%s", VTY_NEWLINE);
274 } else
275 vty_out(vty, " no compression rfc1144%s", VTY_NEWLINE);
276
Philipp73f83d52016-09-02 13:38:01 +0200277 if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 1) {
278 vty_out(vty,
279 " compression v42bis active direction sgsn codewords %d strlen %d%s",
280 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
281 VTY_NEWLINE);
282 } else if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 2) {
283 vty_out(vty,
284 " compression v42bis active direction ms codewords %d strlen %d%s",
285 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
286 VTY_NEWLINE);
287 } else if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 3) {
288 vty_out(vty,
289 " compression v42bis active direction both codewords %d strlen %d%s",
290 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
291 VTY_NEWLINE);
292 } else if (g_cfg->dcomp_v42bis.passive) {
293 vty_out(vty, " compression v42bis passive%s", VTY_NEWLINE);
294 } else
295 vty_out(vty, " no compression v42bis%s", VTY_NEWLINE);
296
Neels Hofmeyr2188a772016-05-20 21:59:55 +0200297#ifdef BUILD_IU
Neels Hofmeyra7a39472017-07-05 15:19:52 +0200298 ranap_iu_vty_config_write(vty, " ");
Neels Hofmeyr2188a772016-05-20 21:59:55 +0200299#endif
300
Harald Welte288be162010-05-01 16:48:27 +0200301 return CMD_SUCCESS;
302}
303
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100304#define SGSN_STR "Configure the SGSN\n"
305#define GGSN_STR "Configure the GGSN information\n"
Harald Weltee300d002010-06-02 12:41:34 +0200306
307DEFUN(cfg_sgsn, cfg_sgsn_cmd,
308 "sgsn",
309 SGSN_STR)
Harald Welte288be162010-05-01 16:48:27 +0200310{
311 vty->node = SGSN_NODE;
312 return CMD_SUCCESS;
313}
314
Harald Weltee300d002010-06-02 12:41:34 +0200315DEFUN(cfg_sgsn_bind_addr, cfg_sgsn_bind_addr_cmd,
316 "gtp local-ip A.B.C.D",
317 "GTP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100318 "Set the IP address for the local GTP bind for the Gp interface (towards the GGSNs)."
319 " Note: in case you would like to run the GGSN on the same machine as the SGSN, you can not run"
320 " both on the same IP address, since both sides are specified to use the same GTP port numbers"
321 " (" OSMO_STRINGIFY_VAL(GTP1C_PORT) " and " OSMO_STRINGIFY_VAL(GTP1U_PORT) ")."
322 " For example, you could use 127.0.0.1 for the SGSN and 127.0.0.2 for the GGSN in such"
323 " situations.\n"
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100324 "IPv4 Address\n")
Harald Weltee300d002010-06-02 12:41:34 +0200325{
326 inet_aton(argv[0], &g_cfg->gtp_listenaddr.sin_addr);
327
328 return CMD_SUCCESS;
329}
330
Harald Welted193cb32010-05-17 22:58:03 +0200331DEFUN(cfg_ggsn_remote_ip, cfg_ggsn_remote_ip_cmd,
332 "ggsn <0-255> remote-ip A.B.C.D",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100333 GGSN_STR "GGSN Number\n"
334 "Configure this static GGSN to use the specified remote IP address.\n"
335 "IPv4 Address\n")
Harald Welted193cb32010-05-17 22:58:03 +0200336{
337 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200338 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welte288be162010-05-01 16:48:27 +0200339
Harald Welted193cb32010-05-17 22:58:03 +0200340 inet_aton(argv[1], &ggc->remote_addr);
Harald Welte288be162010-05-01 16:48:27 +0200341
Harald Welted193cb32010-05-17 22:58:03 +0200342 return CMD_SUCCESS;
343}
344
345#if 0
346DEFUN(cfg_ggsn_remote_port, cfg_ggsn_remote_port_cmd,
347 "ggsn <0-255> remote-port <0-65535>",
348 "")
349{
350 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200351 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welted193cb32010-05-17 22:58:03 +0200352 uint16_t port = atoi(argv[1]);
353
354}
355#endif
356
357DEFUN(cfg_ggsn_gtp_version, cfg_ggsn_gtp_version_cmd,
358 "ggsn <0-255> gtp-version (0|1)",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100359 GGSN_STR "GGSN Number\n" "GTP Version\n"
360 "Version 0\n" "Version 1\n")
Harald Welted193cb32010-05-17 22:58:03 +0200361{
362 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200363 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welted193cb32010-05-17 22:58:03 +0200364
365 if (atoi(argv[1]))
366 ggc->gtp_version = 1;
367 else
368 ggc->gtp_version = 0;
369
370 return CMD_SUCCESS;
371}
372
Pau Espin Pedrolfa120102018-07-09 20:37:47 +0200373/* Seee 3GPP TS 29.060 section 7.2.1 */
374DEFUN(cfg_ggsn_echo_interval, cfg_ggsn_echo_interval_cmd,
375 "ggsn <0-255> echo-interval <1-36000>",
376 GGSN_STR "GGSN Number\n"
377 "Send an echo request to this static GGSN every interval.\n"
378 "Interval between echo requests in seconds.\n")
379{
380 uint32_t id = atoi(argv[0]);
381 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
382
383 ggc->echo_interval = atoi(argv[1]);
384
385 if (ggc->echo_interval < 60)
Pau Espin Pedrolba2e5002019-05-27 17:35:32 +0200386 vty_out(vty, "%% 3GPP TS 29.060 section 7.2.1 states interval should " \
Pau Espin Pedrolfa120102018-07-09 20:37:47 +0200387 "not be lower than 60 seconds, use this value for " \
388 "testing purposes only!%s", VTY_NEWLINE);
389
Alexander Couzens176a4d22018-09-18 20:07:37 +0200390 sgsn_ggsn_ctx_check_echo_timer(ggc);
Pau Espin Pedrolfa120102018-07-09 20:37:47 +0200391 return CMD_SUCCESS;
392}
393
Pau Espin Pedrola83850c2018-07-10 12:43:59 +0200394DEFUN(cfg_ggsn_no_echo_interval, cfg_ggsn_no_echo_interval_cmd,
395 "ggsn <0-255> no echo-interval",
396 GGSN_STR "GGSN Number\n"
397 NO_STR "Send an echo request to this static GGSN every interval.\n")
398{
399 uint32_t id = atoi(argv[0]);
400 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
401
402 ggc->echo_interval = -1;
Alexander Couzens176a4d22018-09-18 20:07:37 +0200403 sgsn_ggsn_ctx_check_echo_timer(ggc);
Pau Espin Pedrola83850c2018-07-10 12:43:59 +0200404
405 return CMD_SUCCESS;
406}
407
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800408DEFUN(cfg_ggsn_dynamic_lookup, cfg_ggsn_dynamic_lookup_cmd,
409 "ggsn dynamic",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100410 GGSN_STR
411 "Enable dynamic resolving of GGSNs based on DNS resolving the APN name like in a GRX-style setup."
412 " Changing this setting requires a restart.\n")
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800413{
414 sgsn->cfg.dynamic_lookup = 1;
415 return CMD_SUCCESS;
416}
417
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800418DEFUN(cfg_grx_ggsn, cfg_grx_ggsn_cmd,
419 "grx-dns-add A.B.C.D",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100420 "Use the specified IP address for DNS-resolving the AP names to GGSN IP addresses\n"
421 "IPv4 address\n")
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800422{
Pau Espin Pedrolb1d1c242018-10-30 17:27:59 +0100423 struct ares_addr_node *node = talloc_zero(tall_sgsn_ctx, struct ares_addr_node);
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800424 node->family = AF_INET;
425 inet_aton(argv[0], &node->addr.addr4);
426
427 node->next = sgsn->ares_servers;
428 sgsn->ares_servers = node;
429 return CMD_SUCCESS;
430}
431
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100432#define APN_STR "Configure the information per APN\n"
433#define APN_GW_STR "The APN gateway name optionally prefixed by '*' (wildcard)\n"
434
435static int add_apn_ggsn_mapping(struct vty *vty, const char *apn_str,
436 const char *imsi_prefix, int ggsn_id)
437{
438 struct apn_ctx *actx;
439 struct sgsn_ggsn_ctx *ggsn;
440
441 ggsn = sgsn_ggsn_ctx_by_id(ggsn_id);
442 if (ggsn == NULL) {
443 vty_out(vty, "%% a GGSN with id %d has not been defined%s",
444 ggsn_id, VTY_NEWLINE);
445 return CMD_WARNING;
446 }
447
448 actx = sgsn_apn_ctx_find_alloc(apn_str, imsi_prefix);
449 if (!actx) {
450 vty_out(vty, "%% unable to create APN context for %s/%s%s",
451 apn_str, imsi_prefix, VTY_NEWLINE);
452 return CMD_WARNING;
453 }
454
455 actx->ggsn = ggsn;
456
457 return CMD_SUCCESS;
458}
459
Harald Welted193cb32010-05-17 22:58:03 +0200460DEFUN(cfg_apn_ggsn, cfg_apn_ggsn_cmd,
461 "apn APNAME ggsn <0-255>",
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100462 APN_STR APN_GW_STR
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100463 "Select the GGSN to use for the given APN gateway prefix\n"
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100464 "The GGSN id")
Harald Welted193cb32010-05-17 22:58:03 +0200465{
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100466
467 return add_apn_ggsn_mapping(vty, argv[0], "", atoi(argv[1]));
Harald Welted193cb32010-05-17 22:58:03 +0200468}
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100469
470DEFUN(cfg_apn_imsi_ggsn, cfg_apn_imsi_ggsn_cmd,
471 "apn APNAME imsi-prefix IMSIPRE ggsn <0-255>",
472 APN_STR APN_GW_STR
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100473 "Select the GGSN to use for the given APN gateway prefix if and only if the IMSI matches the"
474 " given prefix.\n"
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100475 "An IMSI prefix\n"
476 "Select the GGSN to use when APN gateway and IMSI prefix match\n"
477 "The GGSN id")
478{
479
480 return add_apn_ggsn_mapping(vty, argv[0], argv[1], atoi(argv[2]));
481}
Harald Welted193cb32010-05-17 22:58:03 +0200482
483const struct value_string gprs_mm_st_strs[] = {
484 { GMM_DEREGISTERED, "DEREGISTERED" },
485 { GMM_COMMON_PROC_INIT, "COMMON PROCEDURE (INIT)" },
486 { GMM_REGISTERED_NORMAL, "REGISTERED (NORMAL)" },
Harald Weltebffeff82010-06-09 15:50:45 +0200487 { GMM_REGISTERED_SUSPENDED, "REGISTERED (SUSPENDED)" },
Harald Welted193cb32010-05-17 22:58:03 +0200488 { GMM_DEREGISTERED_INIT, "DEREGISTERED (INIT)" },
489 { 0, NULL }
490};
491
Maxc005db72017-10-27 18:43:29 +0200492char *sgsn_gtp_ntoa(struct ul16_t *ul)
Harald Welte471ac7d2016-12-15 19:48:58 +0100493{
Max8492c202017-12-05 17:28:15 +0100494 struct in_addr ia;
495
496 if (gsna2in_addr(&ia, ul) != 0)
Harald Welte471ac7d2016-12-15 19:48:58 +0100497 return "UNKNOWN";
Max8492c202017-12-05 17:28:15 +0100498
499 return inet_ntoa(ia);
Harald Welte471ac7d2016-12-15 19:48:58 +0100500}
501
Harald Welted193cb32010-05-17 22:58:03 +0200502static void vty_dump_pdp(struct vty *vty, const char *pfx,
503 struct sgsn_pdp_ctx *pdp)
504{
Jacob Erlbeck99985b52014-10-13 10:32:00 +0200505 const char *imsi = pdp->mm ? pdp->mm->imsi : "(detaching)";
Harald Welte471ac7d2016-12-15 19:48:58 +0100506 vty_out(vty, "%sPDP Context IMSI: %s, SAPI: %u, NSAPI: %u, TI: %u%s",
507 pfx, imsi, pdp->sapi, pdp->nsapi, pdp->ti, VTY_NEWLINE);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200508 if (pdp->lib) {
Max7933d962017-10-19 16:52:30 +0200509 char apnbuf[APN_MAXLEN + 1];
Harald Weltedfbd2c82017-08-13 00:56:45 +0200510 vty_out(vty, "%s APN: %s%s", pfx,
Max7933d962017-10-19 16:52:30 +0200511 osmo_apn_to_str(apnbuf, pdp->lib->apn_use.v, pdp->lib->apn_use.l),
Harald Weltedfbd2c82017-08-13 00:56:45 +0200512 VTY_NEWLINE);
513 vty_out(vty, "%s PDP Address: %s%s", pfx,
514 gprs_pdpaddr2str(pdp->lib->eua.v, pdp->lib->eua.l),
515 VTY_NEWLINE);
Maxb24af2b2017-12-05 17:54:42 +0100516 vty_out(vty, "%s GTPv%d Local Control(%s / TEIC: 0x%08x) ", pfx, pdp->lib->version,
Maxc005db72017-10-27 18:43:29 +0200517 sgsn_gtp_ntoa(&pdp->lib->gsnlc), pdp->lib->teic_own);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200518 vty_out(vty, "Data(%s / TEID: 0x%08x)%s",
Maxc005db72017-10-27 18:43:29 +0200519 sgsn_gtp_ntoa(&pdp->lib->gsnlu), pdp->lib->teid_own, VTY_NEWLINE);
Maxb24af2b2017-12-05 17:54:42 +0100520 vty_out(vty, "%s GTPv%d Remote Control(%s / TEIC: 0x%08x) ", pfx, pdp->lib->version,
Maxc005db72017-10-27 18:43:29 +0200521 sgsn_gtp_ntoa(&pdp->lib->gsnrc), pdp->lib->teic_gn);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200522 vty_out(vty, "Data(%s / TEID: 0x%08x)%s",
Maxc005db72017-10-27 18:43:29 +0200523 sgsn_gtp_ntoa(&pdp->lib->gsnru), pdp->lib->teid_gn, VTY_NEWLINE);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200524 }
Harald Welte471ac7d2016-12-15 19:48:58 +0100525
Harald Welteefbdee92010-06-10 00:20:12 +0200526 vty_out_rate_ctr_group(vty, " ", pdp->ctrg);
Harald Welted193cb32010-05-17 22:58:03 +0200527}
528
529static void vty_dump_mmctx(struct vty *vty, const char *pfx,
530 struct sgsn_mm_ctx *mm, int pdp)
531{
532 vty_out(vty, "%sMM Context for IMSI %s, IMEI %s, P-TMSI %08x%s",
533 pfx, mm->imsi, mm->imei, mm->p_tmsi, VTY_NEWLINE);
Holger Hans Peter Freyther8ee13e22015-05-18 10:00:03 +0200534 vty_out(vty, "%s MSISDN: %s, TLLI: %08x%s HLR: %s",
Harald Weltef97ee042015-12-25 19:12:21 +0100535 pfx, mm->msisdn, mm->gb.tlli, mm->hlr, VTY_NEWLINE);
Neels Hofmeyr10719b72018-02-21 00:39:36 +0100536 vty_out(vty, "%s MM State: %s, Routeing Area: %s, Cell ID: %u%s",
537 pfx, get_value_string(gprs_mm_st_strs, mm->gmm_state),
538 osmo_rai_name(&mm->ra), mm->gb.cell_id, VTY_NEWLINE);
Harald Welted193cb32010-05-17 22:58:03 +0200539
Harald Welte8acd88f2010-05-18 10:57:45 +0200540 vty_out_rate_ctr_group(vty, " ", mm->ctrg);
541
Harald Welted193cb32010-05-17 22:58:03 +0200542 if (pdp) {
543 struct sgsn_pdp_ctx *pdp;
544
545 llist_for_each_entry(pdp, &mm->pdp_list, list)
546 vty_dump_pdp(vty, " ", pdp);
547 }
548}
549
550DEFUN(show_sgsn, show_sgsn_cmd, "show sgsn",
551 SHOW_STR "Display information about the SGSN")
552{
Jacob Erlbeck80547992014-12-19 19:19:46 +0100553 if (sgsn->gsup_client) {
554 struct ipa_client_conn *link = sgsn->gsup_client->link;
555 vty_out(vty,
556 " Remote authorization: %sconnected to %s:%d via GSUP%s",
557 sgsn->gsup_client->is_connected ? "" : "not ",
558 link->addr, link->port,
559 VTY_NEWLINE);
560 }
Maxbaabc682017-10-20 13:39:57 +0200561 if (sgsn->gsn)
562 vty_out(vty, " GSN: signalling %s, user traffic %s%s",
563 inet_ntoa(sgsn->gsn->gsnc), inet_ntoa(sgsn->gsn->gsnu), VTY_NEWLINE);
564
Harald Welted193cb32010-05-17 22:58:03 +0200565 /* FIXME: statistics */
566 return CMD_SUCCESS;
567}
568
569#define MMCTX_STR "MM Context\n"
570#define INCLUDE_PDP_STR "Include PDP Context Information\n"
571
572#if 0
573DEFUN(show_mmctx_tlli, show_mmctx_tlli_cmd,
574 "show mm-context tlli HEX [pdp]",
575 SHOW_STR MMCTX_STR "Identify by TLLI\n" "TLLI\n" INCLUDE_PDP_STR)
576{
577 uint32_t tlli;
578 struct sgsn_mm_ctx *mm;
579
580 tlli = strtoul(argv[0], NULL, 16);
581 mm = sgsn_mm_ctx_by_tlli(tlli);
582 if (!mm) {
583 vty_out(vty, "No MM context for TLLI %08x%s",
584 tlli, VTY_NEWLINE);
585 return CMD_WARNING;
586 }
587 vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
588 return CMD_SUCCESS;
589}
590#endif
591
592DEFUN(swow_mmctx_imsi, show_mmctx_imsi_cmd,
593 "show mm-context imsi IMSI [pdp]",
594 SHOW_STR MMCTX_STR "Identify by IMSI\n" "IMSI of the MM Context\n"
595 INCLUDE_PDP_STR)
596{
597 struct sgsn_mm_ctx *mm;
598
599 mm = sgsn_mm_ctx_by_imsi(argv[0]);
600 if (!mm) {
601 vty_out(vty, "No MM context for IMSI %s%s",
602 argv[0], VTY_NEWLINE);
603 return CMD_WARNING;
604 }
605 vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
606 return CMD_SUCCESS;
607}
608
609DEFUN(swow_mmctx_all, show_mmctx_all_cmd,
610 "show mm-context all [pdp]",
611 SHOW_STR MMCTX_STR "All MM Contexts\n" INCLUDE_PDP_STR)
612{
613 struct sgsn_mm_ctx *mm;
614
615 llist_for_each_entry(mm, &sgsn_mm_ctxts, list)
616 vty_dump_mmctx(vty, "", mm, argv[0] ? 1 : 0);
617
618 return CMD_SUCCESS;
619}
620
Harald Welted193cb32010-05-17 22:58:03 +0200621DEFUN(show_pdpctx_all, show_pdpctx_all_cmd,
622 "show pdp-context all",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100623 SHOW_STR "Display information on PDP Context\n" "Show everything\n")
Harald Welted193cb32010-05-17 22:58:03 +0200624{
625 struct sgsn_pdp_ctx *pdp;
626
627 llist_for_each_entry(pdp, &sgsn_pdp_ctxts, g_list)
628 vty_dump_pdp(vty, "", pdp);
629
630 return CMD_SUCCESS;
631}
Harald Welte288be162010-05-01 16:48:27 +0200632
Harald Welte7f6da482013-03-19 11:00:13 +0100633
634DEFUN(imsi_acl, cfg_imsi_acl_cmd,
635 "imsi-acl (add|del) IMSI",
636 "Access Control List of foreign IMSIs\n"
637 "Add IMSI to ACL\n"
638 "Remove IMSI from ACL\n"
639 "IMSI of subscriber\n")
640{
Maxef38b4c2018-11-20 10:25:53 +0100641 char imsi_sanitized[GSM23003_IMSI_MAX_DIGITS + 1];
Harald Welte7f6da482013-03-19 11:00:13 +0100642 const char *op = argv[0];
Philipp Maier6ee49d82017-02-28 16:53:07 +0100643 const char *imsi = imsi_sanitized;
Maxf4fa6952018-01-15 12:12:51 +0100644 size_t len = strnlen(argv[1], GSM23003_IMSI_MAX_DIGITS + 1);
Harald Welte7f6da482013-03-19 11:00:13 +0100645 int rc;
646
Maxef38b4c2018-11-20 10:25:53 +0100647 memset(imsi_sanitized, '0', GSM23003_IMSI_MAX_DIGITS);
648 imsi_sanitized[GSM23003_IMSI_MAX_DIGITS] = '\0';
649
Philipp Maier6ee49d82017-02-28 16:53:07 +0100650 /* Sanitize IMSI */
Maxf4fa6952018-01-15 12:12:51 +0100651 if (len > GSM23003_IMSI_MAX_DIGITS) {
652 vty_out(vty, "%% IMSI (%s) too long (max %u digits) -- ignored!%s",
653 argv[1], GSM23003_IMSI_MAX_DIGITS, VTY_NEWLINE);
Philipp Maier6ee49d82017-02-28 16:53:07 +0100654 return CMD_WARNING;
655 }
Maxf4fa6952018-01-15 12:12:51 +0100656
657 osmo_strlcpy(imsi_sanitized + GSM23003_IMSI_MAX_DIGITS - len, argv[1],
658 sizeof(imsi_sanitized) - (GSM23003_IMSI_MAX_DIGITS - len));
Philipp Maier6ee49d82017-02-28 16:53:07 +0100659
Harald Welte7f6da482013-03-19 11:00:13 +0100660 if (!strcmp(op, "add"))
Jacob Erlbeck3b5d4072014-10-24 15:11:03 +0200661 rc = sgsn_acl_add(imsi, g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +0100662 else
Jacob Erlbeck3b5d4072014-10-24 15:11:03 +0200663 rc = sgsn_acl_del(imsi, g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +0100664
665 if (rc < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100666 vty_out(vty, "%% unable to %s ACL%s", op, VTY_NEWLINE);
Harald Welte7f6da482013-03-19 11:00:13 +0100667 return CMD_WARNING;
668 }
669
670 return CMD_SUCCESS;
671}
672
Max93408ae2016-06-28 14:10:16 +0200673DEFUN(cfg_encrypt, cfg_encrypt_cmd,
674 "encryption (GEA0|GEA1|GEA2|GEA3|GEA4)",
675 "Set encryption algorithm for SGSN\n"
676 "Use GEA0 (no encryption)\n"
677 "Use GEA1\nUse GEA2\nUse GEA3\nUse GEA4\n")
678{
Max93408ae2016-06-28 14:10:16 +0200679 enum gprs_ciph_algo c = get_string_value(gprs_cipher_names, argv[0]);
Max086067f2017-05-02 13:03:28 +0200680 if (c != GPRS_ALGO_GEA0) {
681 if (!gprs_cipher_supported(c)) {
682 vty_out(vty, "%% cipher %s is unsupported in current version%s", argv[0], VTY_NEWLINE);
683 return CMD_WARNING;
684 }
685
686 if (!g_cfg->require_authentication) {
687 vty_out(vty, "%% unable to use encryption %s without authentication: please adjust auth-policy%s",
688 argv[0], VTY_NEWLINE);
689 return CMD_WARNING;
690 }
Max93408ae2016-06-28 14:10:16 +0200691 }
692
693 g_cfg->cipher = c;
694
695 return CMD_SUCCESS;
696}
697
Vadim Yanitskiy794f4462019-05-27 05:39:06 +0700698DEFUN(cfg_authentication, cfg_authentication_cmd,
699 "authentication (optional|required)",
Pau Espin Pedrold1463bc2019-06-13 19:03:25 +0200700 "Whether to enforce MS authentication in GERAN (only with auth-policy remote)\n"
701 "Allow MS to attach via GERAN without authentication (default and only possible value for non-remote auth-policy)\n"
702 "Always require authentication (only available for auth-policy remote, default with that auth-policy)\n")
Vadim Yanitskiy794f4462019-05-27 05:39:06 +0700703{
704 int required = (argv[0][0] == 'r');
705
706 if (vty->type != VTY_FILE) {
707 if (g_cfg->auth_policy != SGSN_AUTH_POLICY_REMOTE && required) {
708 vty_out(vty, "%% Authentication is not possible without HLR, "
709 "consider setting 'auth-policy' to 'remote'%s",
710 VTY_NEWLINE);
711 return CMD_WARNING;
712 }
713 }
714
715 g_cfg->require_authentication = required;
716 return CMD_SUCCESS;
717}
718
Harald Welte3dfb5492013-03-19 11:48:54 +0100719DEFUN(cfg_auth_policy, cfg_auth_policy_cmd,
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100720 "auth-policy (accept-all|closed|acl-only|remote)",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100721 "Configure the Authorization policy of the SGSN. This setting determines which subscribers are"
722 " permitted to register to the network.\n"
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100723 "Accept all IMSIs (DANGEROUS)\n"
724 "Accept only home network subscribers or those in the ACL\n"
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100725 "Accept only subscribers in the ACL\n"
726 "Use remote subscription data only (HLR)\n")
Harald Welte3dfb5492013-03-19 11:48:54 +0100727{
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100728 int val = get_string_value(sgsn_auth_pol_strs, argv[0]);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100729 OSMO_ASSERT(val >= SGSN_AUTH_POLICY_OPEN && val <= SGSN_AUTH_POLICY_REMOTE);
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100730 g_cfg->auth_policy = val;
Jacob Erlbeck771573c2014-12-19 18:08:48 +0100731 g_cfg->require_update_location = (val == SGSN_AUTH_POLICY_REMOTE);
Harald Welte3dfb5492013-03-19 11:48:54 +0100732
733 return CMD_SUCCESS;
734}
735
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100736/* Subscriber */
Neels Hofmeyr396f2e62017-09-04 15:13:25 +0200737#include <osmocom/sgsn/gprs_subscriber.h>
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100738
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100739static void subscr_dump_full_vty(struct vty *vty, struct gprs_subscr *gsub, int pending)
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100740{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100741#if 0
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100742 char expire_time[200];
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100743#endif
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100744 struct gsm_auth_tuple *at;
745 int at_idx;
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100746 struct sgsn_subscriber_pdp_data *pdp;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100747
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100748 vty_out(vty, " Authorized: %d%s",
749 gsub->authorized, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100750 vty_out(vty, " LAC: %d/0x%x%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100751 gsub->lac, gsub->lac, VTY_NEWLINE);
752 vty_out(vty, " IMSI: %s%s", gsub->imsi, VTY_NEWLINE);
753 if (gsub->tmsi != GSM_RESERVED_TMSI)
754 vty_out(vty, " TMSI: %08X%s", gsub->tmsi,
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100755 VTY_NEWLINE);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100756 if (gsub->sgsn_data->msisdn_len > 0)
Holger Hans Peter Freytherf7b38262015-04-23 16:58:33 -0400757 vty_out(vty, " MSISDN (BCD): %s%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100758 osmo_hexdump(gsub->sgsn_data->msisdn,
759 gsub->sgsn_data->msisdn_len),
Holger Hans Peter Freytherf7b38262015-04-23 16:58:33 -0400760 VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100761
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100762 if (strlen(gsub->imei) > 0)
763 vty_out(vty, " IMEI: %s%s", gsub->imei, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100764
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100765 for (at_idx = 0; at_idx < ARRAY_SIZE(gsub->sgsn_data->auth_triplets);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100766 at_idx++) {
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100767 at = &gsub->sgsn_data->auth_triplets[at_idx];
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100768 if (at->key_seq == GSM_KEY_SEQ_INVAL)
769 continue;
770
771 vty_out(vty, " A3A8 tuple (used %d times): ",
772 at->use_count);
Harald Welte89837d42016-05-06 23:28:11 +0200773 vty_out(vty, " CKSN: %d, ",
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100774 at->key_seq);
Harald Welte89837d42016-05-06 23:28:11 +0200775 if (at->vec.auth_types & OSMO_AUTH_TYPE_GSM) {
776 vty_out(vty, "RAND: %s, ",
Max34604c22019-02-13 14:11:29 +0100777 osmo_hexdump_nospc(at->vec.rand,
Harald Welte89837d42016-05-06 23:28:11 +0200778 sizeof(at->vec.rand)));
779 vty_out(vty, "SRES: %s, ",
Max34604c22019-02-13 14:11:29 +0100780 osmo_hexdump_nospc(at->vec.sres,
Harald Welte89837d42016-05-06 23:28:11 +0200781 sizeof(at->vec.sres)));
782 vty_out(vty, "Kc: %s%s",
Max34604c22019-02-13 14:11:29 +0100783 osmo_hexdump_nospc(at->vec.kc,
Harald Welte89837d42016-05-06 23:28:11 +0200784 sizeof(at->vec.kc)), VTY_NEWLINE);
785 }
786 if (at->vec.auth_types & OSMO_AUTH_TYPE_UMTS) {
787 vty_out(vty, " AUTN: %s, ",
788 osmo_hexdump(at->vec.autn,
789 sizeof(at->vec.autn)));
790 vty_out(vty, "RES: %s, ",
Max34604c22019-02-13 14:11:29 +0100791 osmo_hexdump_nospc(at->vec.res, at->vec.res_len));
Harald Welte89837d42016-05-06 23:28:11 +0200792 vty_out(vty, "IK: %s, ",
Max34604c22019-02-13 14:11:29 +0100793 osmo_hexdump_nospc(at->vec.ik, sizeof(at->vec.ik)));
Harald Welte89837d42016-05-06 23:28:11 +0200794 vty_out(vty, "CK: %s, ",
Max34604c22019-02-13 14:11:29 +0100795 osmo_hexdump_nospc(at->vec.ck, sizeof(at->vec.ck)));
Harald Welte89837d42016-05-06 23:28:11 +0200796 }
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100797 }
798
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100799 llist_for_each_entry(pdp, &gsub->sgsn_data->pdp_list, list) {
Max34604c22019-02-13 14:11:29 +0100800 vty_out(vty, " PDP info: Id: %d, Type: 0x%04x, APN: '%s'",
801 pdp->context_id, pdp->pdp_type, pdp->apn_str);
802
803 if (pdp->qos_subscribed_len)
804 vty_out(vty, " QoS: %s", osmo_hexdump(pdp->qos_subscribed, pdp->qos_subscribed_len));
805
806 vty_out(vty, "%s", VTY_NEWLINE);
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100807 }
808
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100809#if 0
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100810 /* print the expiration time of a subscriber */
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100811 if (gsub->expire_lu) {
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100812 strftime(expire_time, sizeof(expire_time),
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100813 "%a, %d %b %Y %T %z", localtime(&gsub->expire_lu));
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100814 expire_time[sizeof(expire_time) - 1] = '\0';
815 vty_out(vty, " Expiration Time: %s%s", expire_time, VTY_NEWLINE);
816 }
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100817#endif
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100818
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100819 if (gsub->flags)
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100820 vty_out(vty, " Flags: %s%s%s%s%s%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100821 gsub->flags & GPRS_SUBSCRIBER_FIRST_CONTACT ?
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100822 "FIRST_CONTACT " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100823 gsub->flags & GPRS_SUBSCRIBER_CANCELLED ?
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100824 "CANCELLED " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100825 gsub->flags & GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING ?
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100826 "UPDATE_LOCATION_PENDING " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100827 gsub->flags & GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING ?
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100828 "AUTH_INFO_PENDING " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100829 gsub->flags & GPRS_SUBSCRIBER_ENABLE_PURGE ?
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100830 "ENABLE_PURGE " : "",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100831 VTY_NEWLINE);
832
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100833 vty_out(vty, " Use count: %u%s", gsub->use_count, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100834}
835
Neels Hofmeyr1a9414b2018-09-24 18:14:29 +0200836#define RESET_SGSN_STATE_STR \
837 "Remove all known subscribers, MM contexts and flush BSSGP queues." \
838 " Useful only when running tests against the SGSN\n"
839
Alexander Couzensc503f0a2018-08-07 17:50:04 +0200840DEFUN_HIDDEN(reset_sgsn_state,
841 reset_sgsn_state_cmd,
842 "reset sgsn state",
Neels Hofmeyr1a9414b2018-09-24 18:14:29 +0200843 RESET_SGSN_STATE_STR RESET_SGSN_STATE_STR RESET_SGSN_STATE_STR)
Alexander Couzensc503f0a2018-08-07 17:50:04 +0200844{
845 struct gprs_subscr *subscr, *tmp_subscr;
846 struct sgsn_mm_ctx *mm, *tmp_mm;
847
848 llist_for_each_entry_safe(mm, tmp_mm, &sgsn_mm_ctxts, list)
849 {
850 gsm0408_gprs_access_cancelled(mm, SGSN_ERROR_CAUSE_NONE);
851 }
852 vty_out(vty, "Cancelled MM Ctx. %s", VTY_NEWLINE);
853
854 llist_for_each_entry_safe(subscr, tmp_subscr, gprs_subscribers, entry) {
855 gprs_subscr_get(subscr);
856 gprs_subscr_cancel(subscr);
857 gprs_subscr_put(subscr);
858 }
859 vty_out(vty, "Removed all gprs subscribers.%s", VTY_NEWLINE);
860
861 bssgp_flush_all_queues();
862 vty_out(vty, "Flushed all BSSGPs queues.%s", VTY_NEWLINE);
863
Alexander Couzens35c34942018-09-17 04:39:14 +0200864 gtp_clear_queues(sgsn->gsn);
Alexander Couzensa66f0f22018-09-18 16:09:18 +0200865 vty_out(vty, "Flushed rx & tx queus towards the GGSN.%s", VTY_NEWLINE);
Alexander Couzens35c34942018-09-17 04:39:14 +0200866
Alexander Couzensc503f0a2018-08-07 17:50:04 +0200867 /* remove all queues to bssgp */
868 return CMD_SUCCESS;
869}
870
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100871DEFUN(show_subscr_cache,
872 show_subscr_cache_cmd,
873 "show subscriber cache",
874 SHOW_STR "Show information about subscribers\n"
875 "Display contents of subscriber cache\n")
876{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100877 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100878
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100879 llist_for_each_entry(subscr, gprs_subscribers, entry) {
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100880 vty_out(vty, " Subscriber:%s", VTY_NEWLINE);
881 subscr_dump_full_vty(vty, subscr, 0);
882 }
883
884 return CMD_SUCCESS;
885}
886
887#define UPDATE_SUBSCR_STR "update-subscriber imsi IMSI "
888#define UPDATE_SUBSCR_HELP "Update subscriber list\n" \
889 "Use the IMSI to select the subscriber\n" \
890 "The IMSI\n"
891
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100892#define UPDATE_SUBSCR_INSERT_HELP "Insert data into the subscriber record\n"
893
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100894DEFUN(update_subscr_insert_auth_triplet, update_subscr_insert_auth_triplet_cmd,
895 UPDATE_SUBSCR_STR "insert auth-triplet <1-5> sres SRES rand RAND kc KC",
896 UPDATE_SUBSCR_HELP
897 UPDATE_SUBSCR_INSERT_HELP
898 "Update authentication triplet\n"
899 "Triplet index\n"
900 "Set SRES value\nSRES value (4 byte) in hex\n"
901 "Set RAND value\nRAND value (16 byte) in hex\n"
902 "Set Kc value\nKc value (8 byte) in hex\n")
903{
904 const char *imsi = argv[0];
905 const int cksn = atoi(argv[1]) - 1;
906 const char *sres_str = argv[2];
907 const char *rand_str = argv[3];
908 const char *kc_str = argv[4];
909 struct gsm_auth_tuple at = {0,};
910
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100911 struct gprs_subscr *subscr;
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100912
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100913 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100914 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100915 vty_out(vty, "%% unable get subscriber record for %s%s",
916 imsi, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100917 return CMD_WARNING;
918 }
919
920 OSMO_ASSERT(subscr->sgsn_data);
921
Harald Welte121e9a42016-04-20 13:13:19 +0200922 if (osmo_hexparse(sres_str, &at.vec.sres[0], sizeof(at.vec.sres)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100923 vty_out(vty, "%% invalid SRES value '%s'%s",
924 sres_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100925 goto failed;
926 }
Harald Welte121e9a42016-04-20 13:13:19 +0200927 if (osmo_hexparse(rand_str, &at.vec.rand[0], sizeof(at.vec.rand)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100928 vty_out(vty, "%% invalid RAND value '%s'%s",
929 rand_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(kc_str, &at.vec.kc[0], sizeof(at.vec.kc)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100933 vty_out(vty, "%% invalid Kc value '%s'%s",
934 kc_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100935 goto failed;
936 }
937 at.key_seq = cksn;
938
939 subscr->sgsn_data->auth_triplets[cksn] = at;
940 subscr->sgsn_data->auth_triplets_updated = 1;
941
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100942 gprs_subscr_put(subscr);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100943
944 return CMD_SUCCESS;
945
946failed:
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100947 gprs_subscr_put(subscr);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100948 return CMD_SUCCESS;
949}
950
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100951DEFUN(update_subscr_cancel, update_subscr_cancel_cmd,
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100952 UPDATE_SUBSCR_STR "cancel (update-procedure|subscription-withdraw)",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100953 UPDATE_SUBSCR_HELP
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100954 "Cancel (remove) subscriber record\n"
955 "The MS moved to another SGSN\n"
956 "The subscription is no longer valid\n")
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100957{
958 const char *imsi = argv[0];
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100959 const char *cancel_type = argv[1];
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100960
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100961 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100962
963 subscr = gprs_subscr_get_by_imsi(imsi);
964 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100965 vty_out(vty, "%% no subscriber record for %s%s",
966 imsi, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100967 return CMD_WARNING;
968 }
969
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100970 if (strcmp(cancel_type, "update-procedure") == 0)
971 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
972 else
973 subscr->sgsn_data->error_cause = GMM_CAUSE_IMPL_DETACHED;
974
Jacob Erlbeck37139e52015-01-23 13:52:55 +0100975 gprs_subscr_cancel(subscr);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100976 gprs_subscr_put(subscr);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100977
978 return CMD_SUCCESS;
979}
980
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100981DEFUN(update_subscr_create, update_subscr_create_cmd,
982 UPDATE_SUBSCR_STR "create",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100983 UPDATE_SUBSCR_HELP
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100984 "Create a subscriber entry\n")
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100985{
986 const char *imsi = argv[0];
987
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100988 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100989
990 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100991 if (subscr) {
992 vty_out(vty, "%% subscriber record already exists for %s%s",
993 imsi, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100994 return CMD_WARNING;
995 }
996
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100997 subscr = gprs_subscr_get_or_create(imsi);
998 subscr->keep_in_ram = 1;
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100999 gprs_subscr_put(subscr);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001000
1001 return CMD_SUCCESS;
1002}
1003
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001004DEFUN(update_subscr_destroy, update_subscr_destroy_cmd,
1005 UPDATE_SUBSCR_STR "destroy",
1006 UPDATE_SUBSCR_HELP
1007 "Destroy a subscriber entry\n")
1008{
1009 const char *imsi = argv[0];
1010
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001011 struct gprs_subscr *subscr;
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001012
1013 subscr = gprs_subscr_get_by_imsi(imsi);
1014 if (!subscr) {
1015 vty_out(vty, "%% subscriber record does not exist for %s%s",
1016 imsi, VTY_NEWLINE);
1017 return CMD_WARNING;
1018 }
1019
1020 subscr->keep_in_ram = 0;
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +01001021 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001022 gprs_subscr_cancel(subscr);
1023 if (subscr->use_count > 1)
1024 vty_out(vty, "%% subscriber is still in use%s",
1025 VTY_NEWLINE);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001026 gprs_subscr_put(subscr);
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001027
1028 return CMD_SUCCESS;
1029}
1030
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001031#define UL_ERR_STR "system-failure|data-missing|unexpected-data-value|" \
1032 "unknown-subscriber|roaming-not-allowed"
1033
1034#define UL_ERR_HELP \
1035 "Force error code SystemFailure\n" \
1036 "Force error code DataMissing\n" \
1037 "Force error code UnexpectedDataValue\n" \
1038 "Force error code UnknownSubscriber\n" \
1039 "Force error code RoamingNotAllowed\n"
1040
1041DEFUN(update_subscr_update_location_result, update_subscr_update_location_result_cmd,
1042 UPDATE_SUBSCR_STR "update-location-result (ok|" UL_ERR_STR ")",
1043 UPDATE_SUBSCR_HELP
1044 "Complete the update location procedure\n"
1045 "The update location request succeeded\n"
1046 UL_ERR_HELP)
1047{
1048 const char *imsi = argv[0];
1049 const char *ret_code_str = argv[1];
1050
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001051 struct gprs_subscr *subscr;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001052
Jacob Erlbeckd6267d12015-01-19 11:10:04 +01001053 const struct value_string cause_mapping[] = {
1054 { GMM_CAUSE_NET_FAIL, "system-failure" },
1055 { GMM_CAUSE_INV_MAND_INFO, "data-missing" },
1056 { GMM_CAUSE_PROTO_ERR_UNSPEC, "unexpected-data-value" },
1057 { GMM_CAUSE_IMSI_UNKNOWN, "unknown-subscriber" },
1058 { GMM_CAUSE_GPRS_NOTALLOWED, "roaming-not-allowed" },
1059 { 0, NULL }
1060 };
1061
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001062 subscr = gprs_subscr_get_by_imsi(imsi);
1063 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +01001064 vty_out(vty, "%% unable to get subscriber record for %s%s",
1065 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001066 return CMD_WARNING;
1067 }
Jacob Erlbeckd6267d12015-01-19 11:10:04 +01001068
1069 if (strcmp(ret_code_str, "ok") == 0) {
1070 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001071 subscr->authorized = 1;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +01001072 } else {
1073 subscr->sgsn_data->error_cause =
1074 get_string_value(cause_mapping, ret_code_str);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001075 subscr->authorized = 0;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +01001076 }
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001077
1078 gprs_subscr_update(subscr);
1079
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001080 gprs_subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001081
1082 return CMD_SUCCESS;
1083}
1084
1085DEFUN(update_subscr_update_auth_info, update_subscr_update_auth_info_cmd,
1086 UPDATE_SUBSCR_STR "update-auth-info",
1087 UPDATE_SUBSCR_HELP
1088 "Complete the send authentication info procedure\n")
1089{
1090 const char *imsi = argv[0];
1091
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001092 struct gprs_subscr *subscr;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001093
1094 subscr = gprs_subscr_get_by_imsi(imsi);
1095 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +01001096 vty_out(vty, "%% unable to get subscriber record for %s%s",
1097 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001098 return CMD_WARNING;
1099 }
1100
1101 gprs_subscr_update_auth_info(subscr);
1102
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001103 gprs_subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001104
1105 return CMD_SUCCESS;
1106}
1107
Stefan Sperling88220092018-12-11 14:42:00 +01001108DEFUN(cfg_gsup_ipa_name,
1109 cfg_gsup_ipa_name_cmd,
1110 "gsup ipa-name NAME",
1111 "GSUP Parameters\n"
1112 "Set the IPA name of this SGSN\n"
1113 "A unique name for this SGSN. For example: PLMN + redundancy server number: SGSN-901-70-0. "
1114 "This name is used for GSUP routing and must be set if more than one SGSN is connected to the network. "
1115 "The default is 'SGSN-00-00-00-00-00-00'.\n")
1116{
1117 if (vty->type != VTY_FILE) {
1118 vty_out(vty, "The IPA name cannot be changed at run-time; "
1119 "It can only be set in the configuraton file.%s", VTY_NEWLINE);
1120 return CMD_WARNING;
1121 }
1122
1123 g_cfg->sgsn_ipa_name = talloc_strdup(tall_vty_ctx, argv[0]);
1124 return CMD_SUCCESS;
1125}
1126
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001127DEFUN(cfg_gsup_remote_ip, cfg_gsup_remote_ip_cmd,
1128 "gsup remote-ip A.B.C.D",
1129 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001130 "Set the IP address of the remote GSUP server (e.g. OsmoHLR)."
1131 " This setting only applies if 'auth-policy remote' is used.\n"
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001132 "IPv4 Address\n")
1133{
1134 inet_aton(argv[0], &g_cfg->gsup_server_addr.sin_addr);
1135
1136 return CMD_SUCCESS;
1137}
1138
1139DEFUN(cfg_gsup_remote_port, cfg_gsup_remote_port_cmd,
1140 "gsup remote-port <0-65535>",
1141 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001142 "Set the TCP port of the remote GSUP server, see also 'gsup remote-ip'\n"
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001143 "Remote TCP port\n")
1144{
1145 g_cfg->gsup_server_port = atoi(argv[0]);
1146
1147 return CMD_SUCCESS;
1148}
1149
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001150DEFUN(cfg_gsup_oap_id, cfg_gsup_oap_id_cmd,
1151 "gsup oap-id <0-65535>",
1152 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001153 "Set the OAP client ID for authentication on the GSUP protocol."
1154 " This setting only applies if 'auth-policy remote' is used.\n"
1155 "OAP client ID (0 == disabled)\n")
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001156{
1157 /* VTY ensures range */
1158 g_cfg->oap.client_id = (uint16_t)atoi(argv[0]);
1159 return CMD_SUCCESS;
1160}
1161
1162DEFUN(cfg_gsup_oap_k, cfg_gsup_oap_k_cmd,
1163 "gsup oap-k K",
1164 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001165 "Set the OAP shared secret key K for authentication on the GSUP protocol."
1166 " This setting only applies if auth-policy remote is used.\n"
1167 "K value (16 byte) hex\n")
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001168{
1169 const char *k = argv[0];
1170
1171 g_cfg->oap.secret_k_present = 0;
1172
1173 if ((!k) || (strlen(k) == 0))
1174 goto disable;
1175
1176 int k_len = osmo_hexparse(k,
1177 g_cfg->oap.secret_k,
1178 sizeof(g_cfg->oap.secret_k));
1179 if (k_len != 16) {
1180 vty_out(vty, "%% need exactly 16 octets for oap-k, got %d.%s",
1181 k_len, VTY_NEWLINE);
1182 goto disable;
1183 }
1184
1185 g_cfg->oap.secret_k_present = 1;
1186 return CMD_SUCCESS;
1187
1188disable:
1189 if (g_cfg->oap.client_id > 0) {
1190 vty_out(vty, "%% OAP client ID set, but invalid oap-k value disables OAP.%s",
1191 VTY_NEWLINE);
1192 return CMD_WARNING;
1193 }
1194 return CMD_SUCCESS;
1195}
1196
1197DEFUN(cfg_gsup_oap_opc, cfg_gsup_oap_opc_cmd,
1198 "gsup oap-opc OPC",
1199 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001200 "Set the OAP shared secret OPC for authentication on the GSUP protocol."
1201 " This setting only applies if auth-policy remote is used.\n"
1202 "OPC value (16 byte) hex\n")
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001203{
1204 const char *opc = argv[0];
1205
1206 g_cfg->oap.secret_opc_present = 0;
1207
1208 if ((!opc) || (strlen(opc) == 0))
1209 goto disable;
1210
1211 int opc_len = osmo_hexparse(opc,
1212 g_cfg->oap.secret_opc,
1213 sizeof(g_cfg->oap.secret_opc));
1214 if (opc_len != 16) {
1215 vty_out(vty, "%% need exactly 16 octets for oap-opc, got %d.%s",
1216 opc_len, VTY_NEWLINE);
1217 goto disable;
1218 }
1219
1220 g_cfg->oap.secret_opc_present = 1;
1221 return CMD_SUCCESS;
1222
1223disable:
1224 if (g_cfg->oap.client_id > 0) {
1225 vty_out(vty, "%% OAP client ID set, but invalid oap-opc value disables OAP.%s",
1226 VTY_NEWLINE);
1227 return CMD_WARNING;
1228 }
1229 return CMD_SUCCESS;
1230}
1231
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001232DEFUN(cfg_apn_name, cfg_apn_name_cmd,
1233 "access-point-name NAME",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001234 "Globally allow the given APN name for all subscribers.\n"
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001235 "Add this NAME to the list\n")
1236{
1237 return add_apn_ggsn_mapping(vty, argv[0], "", 0);
1238}
1239
1240DEFUN(cfg_no_apn_name, cfg_no_apn_name_cmd,
1241 "no access-point-name NAME",
1242 NO_STR "Configure a global list of allowed APNs\n"
1243 "Remove entry with NAME\n")
1244{
1245 struct apn_ctx *apn_ctx = sgsn_apn_ctx_by_name(argv[0], "");
1246 if (!apn_ctx)
1247 return CMD_SUCCESS;
1248
1249 sgsn_apn_ctx_free(apn_ctx);
1250 return CMD_SUCCESS;
1251}
1252
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001253DEFUN(cfg_cdr_filename, cfg_cdr_filename_cmd,
1254 "cdr filename NAME",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001255 "CDR\n"
1256 "Set the file name for the call-data-record file, logging the data usage of each subscriber.\n"
1257 "filename\n")
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001258{
1259 talloc_free(g_cfg->cdr.filename);
1260 g_cfg->cdr.filename = talloc_strdup(tall_vty_ctx, argv[0]);
1261 return CMD_SUCCESS;
1262}
1263
1264DEFUN(cfg_no_cdr_filename, cfg_no_cdr_filename_cmd,
1265 "no cdr filename",
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +01001266 NO_STR "CDR\nDisable saving CDR to file\n")
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001267{
1268 talloc_free(g_cfg->cdr.filename);
1269 g_cfg->cdr.filename = NULL;
1270 return CMD_SUCCESS;
1271}
1272
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +01001273DEFUN(cfg_cdr_trap, cfg_cdr_trap_cmd,
1274 "cdr trap",
1275 "CDR\nEnable sending CDR via TRAP CTRL messages\n")
1276{
1277 g_cfg->cdr.trap = true;
1278 return CMD_SUCCESS;
1279}
1280
1281DEFUN(cfg_no_cdr_trap, cfg_no_cdr_trap_cmd,
1282 "no cdr trap",
1283 NO_STR "CDR\nDisable sending CDR via TRAP CTRL messages\n")
1284{
1285 g_cfg->cdr.trap = false;
1286 return CMD_SUCCESS;
1287}
1288
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001289DEFUN(cfg_cdr_interval, cfg_cdr_interval_cmd,
1290 "cdr interval <1-2147483647>",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001291 "CDR\n"
1292 "Set the interval for the call-data-record file\n"
1293 "interval in seconds\n")
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001294{
1295 g_cfg->cdr.interval = atoi(argv[0]);
1296 return CMD_SUCCESS;
1297}
1298
Philippf1f34362016-08-26 17:00:21 +02001299#define COMPRESSION_STR "Configure compression\n"
1300DEFUN(cfg_no_comp_rfc1144, cfg_no_comp_rfc1144_cmd,
1301 "no compression rfc1144",
1302 NO_STR COMPRESSION_STR "disable rfc1144 TCP/IP header compression\n")
1303{
1304 g_cfg->pcomp_rfc1144.active = 0;
1305 g_cfg->pcomp_rfc1144.passive = 0;
1306 return CMD_SUCCESS;
1307}
1308
1309DEFUN(cfg_comp_rfc1144, cfg_comp_rfc1144_cmd,
1310 "compression rfc1144 active slots <1-256>",
1311 COMPRESSION_STR
1312 "RFC1144 Header compresion scheme\n"
1313 "Compression is actively proposed\n"
1314 "Number of compression state slots\n"
1315 "Number of compression state slots\n")
1316{
1317 g_cfg->pcomp_rfc1144.active = 1;
1318 g_cfg->pcomp_rfc1144.passive = 1;
1319 g_cfg->pcomp_rfc1144.s01 = atoi(argv[0]) - 1;
1320 return CMD_SUCCESS;
1321}
1322
1323DEFUN(cfg_comp_rfc1144p, cfg_comp_rfc1144p_cmd,
1324 "compression rfc1144 passive",
1325 COMPRESSION_STR
1326 "RFC1144 Header compresion scheme\n"
1327 "Compression is available on request\n")
1328{
1329 g_cfg->pcomp_rfc1144.active = 0;
1330 g_cfg->pcomp_rfc1144.passive = 1;
1331 return CMD_SUCCESS;
1332}
1333
Philipp73f83d52016-09-02 13:38:01 +02001334DEFUN(cfg_no_comp_v42bis, cfg_no_comp_v42bis_cmd,
1335 "no compression v42bis",
1336 NO_STR COMPRESSION_STR "disable V.42bis data compression\n")
1337{
1338 g_cfg->dcomp_v42bis.active = 0;
1339 g_cfg->dcomp_v42bis.passive = 0;
1340 return CMD_SUCCESS;
1341}
1342
1343DEFUN(cfg_comp_v42bis, cfg_comp_v42bis_cmd,
1344 "compression v42bis active direction (ms|sgsn|both) codewords <512-65535> strlen <6-250>",
1345 COMPRESSION_STR
1346 "V.42bis data compresion scheme\n"
1347 "Compression is actively proposed\n"
1348 "Direction in which the compression shall be active (p0)\n"
1349 "Compress ms->sgsn direction only\n"
1350 "Compress sgsn->ms direction only\n"
1351 "Both directions\n"
1352 "Number of codewords (p1)\n"
1353 "Number of codewords\n"
1354 "Maximum string length (p2)\n" "Maximum string length\n")
1355{
1356 g_cfg->dcomp_v42bis.active = 1;
1357 g_cfg->dcomp_v42bis.passive = 1;
1358
1359 switch (argv[0][0]) {
1360 case 'm':
1361 g_cfg->dcomp_v42bis.p0 = 1;
1362 break;
1363 case 's':
1364 g_cfg->dcomp_v42bis.p0 = 2;
1365 break;
1366 case 'b':
1367 g_cfg->dcomp_v42bis.p0 = 3;
1368 break;
1369 }
1370
1371 g_cfg->dcomp_v42bis.p1 = atoi(argv[1]);
1372 g_cfg->dcomp_v42bis.p2 = atoi(argv[2]);
1373 return CMD_SUCCESS;
1374}
1375
1376DEFUN(cfg_comp_v42bisp, cfg_comp_v42bisp_cmd,
1377 "compression v42bis passive",
1378 COMPRESSION_STR
1379 "V.42bis data compresion scheme\n"
1380 "Compression is available on request\n")
1381{
1382 g_cfg->dcomp_v42bis.active = 0;
1383 g_cfg->dcomp_v42bis.passive = 1;
1384 return CMD_SUCCESS;
1385}
1386
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001387int sgsn_vty_init(struct sgsn_config *cfg)
Harald Welte288be162010-05-01 16:48:27 +02001388{
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001389 g_cfg = cfg;
1390
Harald Welted193cb32010-05-17 22:58:03 +02001391 install_element_ve(&show_sgsn_cmd);
1392 //install_element_ve(&show_mmctx_tlli_cmd);
1393 install_element_ve(&show_mmctx_imsi_cmd);
1394 install_element_ve(&show_mmctx_all_cmd);
1395 install_element_ve(&show_pdpctx_all_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001396 install_element_ve(&show_subscr_cache_cmd);
1397
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01001398 install_element(ENABLE_NODE, &update_subscr_insert_auth_triplet_cmd);
Jacob Erlbeckd9193432015-01-19 14:11:46 +01001399 install_element(ENABLE_NODE, &update_subscr_create_cmd);
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001400 install_element(ENABLE_NODE, &update_subscr_destroy_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001401 install_element(ENABLE_NODE, &update_subscr_cancel_cmd);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001402 install_element(ENABLE_NODE, &update_subscr_update_location_result_cmd);
1403 install_element(ENABLE_NODE, &update_subscr_update_auth_info_cmd);
Alexander Couzensc503f0a2018-08-07 17:50:04 +02001404 install_element(ENABLE_NODE, &reset_sgsn_state_cmd);
Harald Welte288be162010-05-01 16:48:27 +02001405
1406 install_element(CONFIG_NODE, &cfg_sgsn_cmd);
1407 install_node(&sgsn_node, config_write_sgsn);
Harald Weltee300d002010-06-02 12:41:34 +02001408 install_element(SGSN_NODE, &cfg_sgsn_bind_addr_cmd);
Harald Welted193cb32010-05-17 22:58:03 +02001409 install_element(SGSN_NODE, &cfg_ggsn_remote_ip_cmd);
1410 //install_element(SGSN_NODE, &cfg_ggsn_remote_port_cmd);
1411 install_element(SGSN_NODE, &cfg_ggsn_gtp_version_cmd);
Pau Espin Pedrolfa120102018-07-09 20:37:47 +02001412 install_element(SGSN_NODE, &cfg_ggsn_echo_interval_cmd);
Pau Espin Pedrola83850c2018-07-10 12:43:59 +02001413 install_element(SGSN_NODE, &cfg_ggsn_no_echo_interval_cmd);
Harald Welte7f6da482013-03-19 11:00:13 +01001414 install_element(SGSN_NODE, &cfg_imsi_acl_cmd);
Harald Welte3dfb5492013-03-19 11:48:54 +01001415 install_element(SGSN_NODE, &cfg_auth_policy_cmd);
Vadim Yanitskiy794f4462019-05-27 05:39:06 +07001416 install_element(SGSN_NODE, &cfg_authentication_cmd);
Max93408ae2016-06-28 14:10:16 +02001417 install_element(SGSN_NODE, &cfg_encrypt_cmd);
Stefan Sperling88220092018-12-11 14:42:00 +01001418 install_element(SGSN_NODE, &cfg_gsup_ipa_name_cmd);
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001419 install_element(SGSN_NODE, &cfg_gsup_remote_ip_cmd);
1420 install_element(SGSN_NODE, &cfg_gsup_remote_port_cmd);
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001421 install_element(SGSN_NODE, &cfg_gsup_oap_id_cmd);
1422 install_element(SGSN_NODE, &cfg_gsup_oap_k_cmd);
1423 install_element(SGSN_NODE, &cfg_gsup_oap_opc_cmd);
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +01001424 install_element(SGSN_NODE, &cfg_apn_ggsn_cmd);
1425 install_element(SGSN_NODE, &cfg_apn_imsi_ggsn_cmd);
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001426 install_element(SGSN_NODE, &cfg_apn_name_cmd);
1427 install_element(SGSN_NODE, &cfg_no_apn_name_cmd);
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001428 install_element(SGSN_NODE, &cfg_cdr_filename_cmd);
1429 install_element(SGSN_NODE, &cfg_no_cdr_filename_cmd);
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +01001430 install_element(SGSN_NODE, &cfg_cdr_trap_cmd);
1431 install_element(SGSN_NODE, &cfg_no_cdr_trap_cmd);
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001432 install_element(SGSN_NODE, &cfg_cdr_interval_cmd);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001433 install_element(SGSN_NODE, &cfg_ggsn_dynamic_lookup_cmd);
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +08001434 install_element(SGSN_NODE, &cfg_grx_ggsn_cmd);
Harald Welte288be162010-05-01 16:48:27 +02001435
Harald Welte94508822015-08-15 19:08:21 +02001436 install_element(SGSN_NODE, &cfg_sgsn_T3312_cmd);
1437 install_element(SGSN_NODE, &cfg_sgsn_T3322_cmd);
1438 install_element(SGSN_NODE, &cfg_sgsn_T3350_cmd);
1439 install_element(SGSN_NODE, &cfg_sgsn_T3360_cmd);
1440 install_element(SGSN_NODE, &cfg_sgsn_T3370_cmd);
1441 install_element(SGSN_NODE, &cfg_sgsn_T3313_cmd);
1442 install_element(SGSN_NODE, &cfg_sgsn_T3314_cmd);
1443 install_element(SGSN_NODE, &cfg_sgsn_T3316_cmd);
1444 install_element(SGSN_NODE, &cfg_sgsn_T3385_cmd);
1445 install_element(SGSN_NODE, &cfg_sgsn_T3386_cmd);
1446 install_element(SGSN_NODE, &cfg_sgsn_T3395_cmd);
1447 install_element(SGSN_NODE, &cfg_sgsn_T3397_cmd);
1448
Philippf1f34362016-08-26 17:00:21 +02001449 install_element(SGSN_NODE, &cfg_no_comp_rfc1144_cmd);
1450 install_element(SGSN_NODE, &cfg_comp_rfc1144_cmd);
1451 install_element(SGSN_NODE, &cfg_comp_rfc1144p_cmd);
Philipp73f83d52016-09-02 13:38:01 +02001452 install_element(SGSN_NODE, &cfg_no_comp_v42bis_cmd);
1453 install_element(SGSN_NODE, &cfg_comp_v42bis_cmd);
1454 install_element(SGSN_NODE, &cfg_comp_v42bisp_cmd);
Neels Hofmeyr2188a772016-05-20 21:59:55 +02001455
1456#ifdef BUILD_IU
Neels Hofmeyra7a39472017-07-05 15:19:52 +02001457 ranap_iu_vty_init(SGSN_NODE, &g_cfg->iu.rab_assign_addr_enc);
Neels Hofmeyr2188a772016-05-20 21:59:55 +02001458#endif
Harald Welte288be162010-05-01 16:48:27 +02001459 return 0;
1460}
1461
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001462int sgsn_parse_config(const char *config_file)
Harald Welte288be162010-05-01 16:48:27 +02001463{
1464 int rc;
1465
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001466 /* make sure sgsn_vty_init() was called before this */
1467 OSMO_ASSERT(g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +01001468
Harald Welte94508822015-08-15 19:08:21 +02001469 g_cfg->timers.T3312 = GSM0408_T3312_SECS;
1470 g_cfg->timers.T3322 = GSM0408_T3322_SECS;
1471 g_cfg->timers.T3350 = GSM0408_T3350_SECS;
1472 g_cfg->timers.T3360 = GSM0408_T3360_SECS;
1473 g_cfg->timers.T3370 = GSM0408_T3370_SECS;
1474 g_cfg->timers.T3313 = GSM0408_T3313_SECS;
1475 g_cfg->timers.T3314 = GSM0408_T3314_SECS;
1476 g_cfg->timers.T3316 = GSM0408_T3316_SECS;
1477 g_cfg->timers.T3385 = GSM0408_T3385_SECS;
1478 g_cfg->timers.T3386 = GSM0408_T3386_SECS;
1479 g_cfg->timers.T3395 = GSM0408_T3395_SECS;
1480 g_cfg->timers.T3397 = GSM0408_T3397_SECS;
1481
Harald Weltedcccb182010-05-16 20:52:23 +02001482 rc = vty_read_config_file(config_file, NULL);
Harald Welte288be162010-05-01 16:48:27 +02001483 if (rc < 0) {
1484 fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
1485 return rc;
1486 }
1487
Neels Hofmeyr27355c92017-02-24 06:28:31 +01001488 if (g_cfg->auth_policy == SGSN_AUTH_POLICY_REMOTE
1489 && !(g_cfg->gsup_server_addr.sin_addr.s_addr
1490 && g_cfg->gsup_server_port)) {
1491 fprintf(stderr, "Configuration error:"
1492 " 'auth-policy remote' requires both"
1493 " 'gsup remote-ip' and 'gsup remote-port'\n");
1494 return -EINVAL;
1495 }
1496
Harald Welte288be162010-05-01 16:48:27 +02001497 return 0;
1498}