blob: 9d1d86d39077a8cef69862fe5474539555d498ca [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>
Harald Welte288be162010-05-01 16:48:27 +020026
Pablo Neira Ayuso136f4532011-03-22 16:47:59 +010027#include <osmocom/core/talloc.h>
28#include <osmocom/core/utils.h>
29#include <osmocom/core/rate_ctr.h>
Harald Welte53373bc2016-04-20 17:11:43 +020030#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
Harald Welte7e82b742017-08-12 13:43:54 +020031#include <osmocom/gsm/apn.h>
Harald Welte288be162010-05-01 16:48:27 +020032
Neels Hofmeyr396f2e62017-09-04 15:13:25 +020033#include <osmocom/sgsn/debug.h>
34#include <osmocom/sgsn/sgsn.h>
Harald Welteea34a4e2012-06-16 14:59:56 +080035#include <osmocom/gprs/gprs_ns.h>
Neels Hofmeyr396f2e62017-09-04 15:13:25 +020036#include <osmocom/sgsn/gprs_sgsn.h>
37#include <osmocom/sgsn/vty.h>
38#include <osmocom/sgsn/gsup_client.h>
Harald Welte288be162010-05-01 16:48:27 +020039
Harald Welte4b037e42010-05-19 19:45:32 +020040#include <osmocom/vty/command.h>
41#include <osmocom/vty/vty.h>
Pablo Neira Ayuso6110a3f2011-03-28 19:35:00 +020042#include <osmocom/vty/misc.h>
Max93408ae2016-06-28 14:10:16 +020043#include <osmocom/crypt/gprs_cipher.h>
Jacob Erlbeck80547992014-12-19 19:19:46 +010044#include <osmocom/abis/ipa.h>
45
Harald Welted193cb32010-05-17 22:58:03 +020046#include <pdp.h>
Maxbaabc682017-10-20 13:39:57 +020047#include <gtp.h>
Harald Welted193cb32010-05-17 22:58:03 +020048
Neels Hofmeyr2188a772016-05-20 21:59:55 +020049#include "../../bscconfig.h"
50
51#ifdef BUILD_IU
Neels Hofmeyra7a39472017-07-05 15:19:52 +020052#include <osmocom/ranap/iu_client.h>
Neels Hofmeyr2188a772016-05-20 21:59:55 +020053#endif
54
Neels Hofmeyree6cfdc2017-07-13 02:03:50 +020055extern void *tall_bsc_ctx;
56
Harald Welte288be162010-05-01 16:48:27 +020057static struct sgsn_config *g_cfg = NULL;
58
Jacob Erlbeck106f5472014-11-04 10:08:37 +010059const struct value_string sgsn_auth_pol_strs[] = {
60 { SGSN_AUTH_POLICY_OPEN, "accept-all" },
61 { SGSN_AUTH_POLICY_CLOSED, "closed" },
62 { SGSN_AUTH_POLICY_ACL_ONLY, "acl-only" },
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +010063 { SGSN_AUTH_POLICY_REMOTE, "remote" },
Jacob Erlbeck106f5472014-11-04 10:08:37 +010064 { 0, NULL }
65};
66
Harald Welte94508822015-08-15 19:08:21 +020067/* Section 11.2.2 / Table 11.3a GPRS Mobility management timers – MS side */
68#define GSM0408_T3312_SECS (10*60) /* periodic RAU interval, default 54min */
69
70/* Section 11.2.2 / Table 11.4 MM timers netwokr side */
71#define GSM0408_T3322_SECS 6 /* DETACH_REQ -> DETACH_ACC */
72#define GSM0408_T3350_SECS 6 /* waiting for ATT/RAU/TMSI COMPL */
73#define GSM0408_T3360_SECS 6 /* waiting for AUTH/CIPH RESP */
74#define GSM0408_T3370_SECS 6 /* waiting for ID RESP */
75
Alexander Couzens5ba6fb32017-01-31 18:04:27 +010076/* Section 11.2.2 / Table 11.4a MM timers network side */
Harald Welte94508822015-08-15 19:08:21 +020077#define GSM0408_T3313_SECS 30 /* waiting for paging response */
78#define GSM0408_T3314_SECS 44 /* force to STBY on expiry, Ready timer */
79#define GSM0408_T3316_SECS 44
80
81/* Section 11.3 / Table 11.2d Timers of Session Management - network side */
82#define GSM0408_T3385_SECS 8 /* wait for ACT PDP CTX REQ */
83#define GSM0408_T3386_SECS 8 /* wait for MODIFY PDP CTX ACK */
84#define GSM0408_T3395_SECS 8 /* wait for DEACT PDP CTX ACK */
85#define GSM0408_T3397_SECS 8 /* wait for DEACT AA PDP CTX ACK */
86
87#define DECLARE_TIMER(number, doc) \
88 DEFUN(cfg_sgsn_T##number, \
89 cfg_sgsn_T##number##_cmd, \
90 "timer t" #number " <0-65535>", \
91 "Configure GPRS Timers\n" \
Holger Hans Peter Freytherfe60cfb2015-11-02 12:55:07 +010092 doc "\nTimer Value in seconds\n") \
Harald Welte94508822015-08-15 19:08:21 +020093{ \
94 int value = atoi(argv[0]); \
95 \
96 if (value < 0 || value > 65535) { \
97 vty_out(vty, "Timer value %s out of range.%s", \
98 argv[0], VTY_NEWLINE); \
99 return CMD_WARNING; \
100 } \
101 \
102 g_cfg->timers.T##number = value; \
103 return CMD_SUCCESS; \
104}
105
106DECLARE_TIMER(3312, "Periodic RA Update timer (s)")
Neels Hofmeyr65482c92015-10-19 14:37:12 +0200107DECLARE_TIMER(3322, "Detach request -> accept timer (s)")
Harald Welte94508822015-08-15 19:08:21 +0200108DECLARE_TIMER(3350, "Waiting for ATT/RAU/TMSI_COMPL timer (s)")
109DECLARE_TIMER(3360, "Waiting for AUTH/CIPH response timer (s)")
110DECLARE_TIMER(3370, "Waiting for IDENTITY response timer (s)")
111
112DECLARE_TIMER(3313, "Waiting for paging response timer (s)")
113DECLARE_TIMER(3314, "Force to STANDBY on expiry timer (s)")
Holger Hans Peter Freytherfe60cfb2015-11-02 12:55:07 +0100114DECLARE_TIMER(3316, "AA-Ready timer (s)")
Harald Welte94508822015-08-15 19:08:21 +0200115
116DECLARE_TIMER(3385, "Wait for ACT PDP CTX REQ timer (s)")
117DECLARE_TIMER(3386, "Wait for MODIFY PDP CTX ACK timer (s)")
118DECLARE_TIMER(3395, "Wait for DEACT PDP CTX ACK timer (s)")
119DECLARE_TIMER(3397, "Wait for DEACT AA PDP CTX ACK timer (s)")
120
Holger Hans Peter Freythera2730302014-03-23 18:08:26 +0100121char *gprs_pdpaddr2str(uint8_t *pdpa, uint8_t len)
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200122{
123 static char str[INET6_ADDRSTRLEN + 10];
124
125 if (!pdpa || len < 2)
126 return "none";
127
128 switch (pdpa[0] & 0x0f) {
129 case PDP_TYPE_ORG_IETF:
130 switch (pdpa[1]) {
131 case PDP_TYPE_N_IETF_IPv4:
132 if (len < 2 + 4)
133 break;
134 strcpy(str, "IPv4 ");
135 inet_ntop(AF_INET, pdpa+2, str+5, sizeof(str)-5);
136 return str;
137 case PDP_TYPE_N_IETF_IPv6:
138 if (len < 2 + 8)
139 break;
140 strcpy(str, "IPv6 ");
141 inet_ntop(AF_INET6, pdpa+2, str+5, sizeof(str)-5);
142 return str;
143 default:
144 break;
145 }
146 break;
147 case PDP_TYPE_ORG_ETSI:
148 if (pdpa[1] == PDP_TYPE_N_ETSI_PPP)
149 return "PPP";
150 break;
151 default:
152 break;
153 }
154
155 return "invalid";
156}
157
Harald Welte288be162010-05-01 16:48:27 +0200158static struct cmd_node sgsn_node = {
159 SGSN_NODE,
Harald Welte570ce242012-08-17 13:16:10 +0200160 "%s(config-sgsn)# ",
Harald Welte288be162010-05-01 16:48:27 +0200161 1,
162};
163
164static int config_write_sgsn(struct vty *vty)
165{
Harald Welte77289c22010-05-18 14:32:29 +0200166 struct sgsn_ggsn_ctx *gctx;
Harald Welte7f6da482013-03-19 11:00:13 +0100167 struct imsi_acl_entry *acl;
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100168 struct apn_ctx *actx;
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800169 struct ares_addr_node *server;
Harald Welte288be162010-05-01 16:48:27 +0200170
171 vty_out(vty, "sgsn%s", VTY_NEWLINE);
172
Harald Weltee300d002010-06-02 12:41:34 +0200173 vty_out(vty, " gtp local-ip %s%s",
174 inet_ntoa(g_cfg->gtp_listenaddr.sin_addr), VTY_NEWLINE);
175
Harald Welted193cb32010-05-17 22:58:03 +0200176 llist_for_each_entry(gctx, &sgsn_ggsn_ctxts, list) {
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800177 if (gctx->id == UINT32_MAX)
178 continue;
179
Harald Welteff3bde82010-05-19 15:09:09 +0200180 vty_out(vty, " ggsn %u remote-ip %s%s", gctx->id,
Harald Welted193cb32010-05-17 22:58:03 +0200181 inet_ntoa(gctx->remote_addr), VTY_NEWLINE);
Harald Welteff3bde82010-05-19 15:09:09 +0200182 vty_out(vty, " ggsn %u gtp-version %u%s", gctx->id,
Harald Welted193cb32010-05-17 22:58:03 +0200183 gctx->gtp_version, VTY_NEWLINE);
Harald Welte288be162010-05-01 16:48:27 +0200184 }
185
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800186 if (sgsn->cfg.dynamic_lookup)
187 vty_out(vty, " ggsn dynamic%s", VTY_NEWLINE);
188
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800189 for (server = sgsn->ares_servers; server; server = server->next)
190 vty_out(vty, " grx-dns-add %s%s", inet_ntoa(server->addr.addr4), VTY_NEWLINE);
191
Max93408ae2016-06-28 14:10:16 +0200192 if (g_cfg->cipher != GPRS_ALGO_GEA0)
193 vty_out(vty, " encryption %s%s",
194 get_value_string(gprs_cipher_names, g_cfg->cipher),
195 VTY_NEWLINE);
Jacob Erlbeck39f040d2014-12-18 12:46:47 +0100196 if (g_cfg->gsup_server_addr.sin_addr.s_addr)
197 vty_out(vty, " gsup remote-ip %s%s",
198 inet_ntoa(g_cfg->gsup_server_addr.sin_addr), VTY_NEWLINE);
199 if (g_cfg->gsup_server_port)
200 vty_out(vty, " gsup remote-port %d%s",
201 g_cfg->gsup_server_port, VTY_NEWLINE);
Max176b62a2016-07-04 11:09:07 +0200202 vty_out(vty, " auth-policy %s%s",
203 get_value_string(sgsn_auth_pol_strs, g_cfg->auth_policy),
204 VTY_NEWLINE);
Neels Hofmeyr568a7272015-10-12 11:57:38 +0200205
206 vty_out(vty, " gsup oap-id %d%s",
207 (int)g_cfg->oap.client_id, VTY_NEWLINE);
208 if (g_cfg->oap.secret_k_present != 0)
209 vty_out(vty, " gsup oap-k %s%s",
210 osmo_hexdump_nospc(g_cfg->oap.secret_k, sizeof(g_cfg->oap.secret_k)),
211 VTY_NEWLINE);
212 if (g_cfg->oap.secret_opc_present != 0)
213 vty_out(vty, " gsup oap-opc %s%s",
214 osmo_hexdump_nospc(g_cfg->oap.secret_opc, sizeof(g_cfg->oap.secret_opc)),
215 VTY_NEWLINE);
216
Harald Welte7f6da482013-03-19 11:00:13 +0100217 llist_for_each_entry(acl, &g_cfg->imsi_acl, list)
218 vty_out(vty, " imsi-acl add %s%s", acl->imsi, VTY_NEWLINE);
219
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100220 if (llist_empty(&sgsn_apn_ctxts))
221 vty_out(vty, " ! apn * ggsn 0%s", VTY_NEWLINE);
222 llist_for_each_entry(actx, &sgsn_apn_ctxts, list) {
223 if (strlen(actx->imsi_prefix) > 0)
Holger Hans Peter Freytherb7ae0b32015-05-29 15:11:55 +0200224 vty_out(vty, " apn %s imsi-prefix %s ggsn %u%s",
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100225 actx->name, actx->imsi_prefix, actx->ggsn->id,
226 VTY_NEWLINE);
227 else
Holger Hans Peter Freytherb7ae0b32015-05-29 15:11:55 +0200228 vty_out(vty, " apn %s ggsn %u%s", actx->name,
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100229 actx->ggsn->id, VTY_NEWLINE);
230 }
231
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +0200232 if (g_cfg->cdr.filename)
233 vty_out(vty, " cdr filename %s%s", g_cfg->cdr.filename, VTY_NEWLINE);
234 else
235 vty_out(vty, " no cdr filename%s", VTY_NEWLINE);
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +0100236 if (g_cfg->cdr.trap)
237 vty_out(vty, " cdr trap%s", VTY_NEWLINE);
238 else
239 vty_out(vty, " no cdr trap%s", VTY_NEWLINE);
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +0200240 vty_out(vty, " cdr interval %d%s", g_cfg->cdr.interval, VTY_NEWLINE);
241
Harald Welte94508822015-08-15 19:08:21 +0200242 vty_out(vty, " timer t3312 %d%s", g_cfg->timers.T3312, VTY_NEWLINE);
243 vty_out(vty, " timer t3322 %d%s", g_cfg->timers.T3322, VTY_NEWLINE);
244 vty_out(vty, " timer t3350 %d%s", g_cfg->timers.T3350, VTY_NEWLINE);
245 vty_out(vty, " timer t3360 %d%s", g_cfg->timers.T3360, VTY_NEWLINE);
246 vty_out(vty, " timer t3370 %d%s", g_cfg->timers.T3370, VTY_NEWLINE);
247 vty_out(vty, " timer t3313 %d%s", g_cfg->timers.T3313, VTY_NEWLINE);
248 vty_out(vty, " timer t3314 %d%s", g_cfg->timers.T3314, VTY_NEWLINE);
249 vty_out(vty, " timer t3316 %d%s", g_cfg->timers.T3316, VTY_NEWLINE);
250 vty_out(vty, " timer t3385 %d%s", g_cfg->timers.T3385, VTY_NEWLINE);
251 vty_out(vty, " timer t3386 %d%s", g_cfg->timers.T3386, VTY_NEWLINE);
252 vty_out(vty, " timer t3395 %d%s", g_cfg->timers.T3395, VTY_NEWLINE);
253 vty_out(vty, " timer t3397 %d%s", g_cfg->timers.T3397, VTY_NEWLINE);
254
Philippf1f34362016-08-26 17:00:21 +0200255 if (g_cfg->pcomp_rfc1144.active) {
256 vty_out(vty, " compression rfc1144 active slots %d%s",
257 g_cfg->pcomp_rfc1144.s01 + 1, VTY_NEWLINE);
258 } else if (g_cfg->pcomp_rfc1144.passive) {
259 vty_out(vty, " compression rfc1144 passive%s", VTY_NEWLINE);
260 } else
261 vty_out(vty, " no compression rfc1144%s", VTY_NEWLINE);
262
Philipp73f83d52016-09-02 13:38:01 +0200263 if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 1) {
264 vty_out(vty,
265 " compression v42bis active direction sgsn codewords %d strlen %d%s",
266 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
267 VTY_NEWLINE);
268 } else if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 2) {
269 vty_out(vty,
270 " compression v42bis active direction ms codewords %d strlen %d%s",
271 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
272 VTY_NEWLINE);
273 } else if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 3) {
274 vty_out(vty,
275 " compression v42bis active direction both 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.passive) {
279 vty_out(vty, " compression v42bis passive%s", VTY_NEWLINE);
280 } else
281 vty_out(vty, " no compression v42bis%s", VTY_NEWLINE);
282
Neels Hofmeyr2188a772016-05-20 21:59:55 +0200283#ifdef BUILD_IU
Neels Hofmeyra7a39472017-07-05 15:19:52 +0200284 ranap_iu_vty_config_write(vty, " ");
Neels Hofmeyr2188a772016-05-20 21:59:55 +0200285#endif
286
Harald Welte288be162010-05-01 16:48:27 +0200287 return CMD_SUCCESS;
288}
289
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100290#define SGSN_STR "Configure the SGSN\n"
291#define GGSN_STR "Configure the GGSN information\n"
Harald Weltee300d002010-06-02 12:41:34 +0200292
293DEFUN(cfg_sgsn, cfg_sgsn_cmd,
294 "sgsn",
295 SGSN_STR)
Harald Welte288be162010-05-01 16:48:27 +0200296{
297 vty->node = SGSN_NODE;
298 return CMD_SUCCESS;
299}
300
Harald Weltee300d002010-06-02 12:41:34 +0200301DEFUN(cfg_sgsn_bind_addr, cfg_sgsn_bind_addr_cmd,
302 "gtp local-ip A.B.C.D",
303 "GTP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100304 "Set the IP address for the local GTP bind for the Gp interface (towards the GGSNs)."
305 " Note: in case you would like to run the GGSN on the same machine as the SGSN, you can not run"
306 " both on the same IP address, since both sides are specified to use the same GTP port numbers"
307 " (" OSMO_STRINGIFY_VAL(GTP1C_PORT) " and " OSMO_STRINGIFY_VAL(GTP1U_PORT) ")."
308 " For example, you could use 127.0.0.1 for the SGSN and 127.0.0.2 for the GGSN in such"
309 " situations.\n"
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100310 "IPv4 Address\n")
Harald Weltee300d002010-06-02 12:41:34 +0200311{
312 inet_aton(argv[0], &g_cfg->gtp_listenaddr.sin_addr);
313
314 return CMD_SUCCESS;
315}
316
Harald Welted193cb32010-05-17 22:58:03 +0200317DEFUN(cfg_ggsn_remote_ip, cfg_ggsn_remote_ip_cmd,
318 "ggsn <0-255> remote-ip A.B.C.D",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100319 GGSN_STR "GGSN Number\n"
320 "Configure this static GGSN to use the specified remote IP address.\n"
321 "IPv4 Address\n")
Harald Welted193cb32010-05-17 22:58:03 +0200322{
323 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200324 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welte288be162010-05-01 16:48:27 +0200325
Harald Welted193cb32010-05-17 22:58:03 +0200326 inet_aton(argv[1], &ggc->remote_addr);
Harald Welte288be162010-05-01 16:48:27 +0200327
Harald Welted193cb32010-05-17 22:58:03 +0200328 return CMD_SUCCESS;
329}
330
331#if 0
332DEFUN(cfg_ggsn_remote_port, cfg_ggsn_remote_port_cmd,
333 "ggsn <0-255> remote-port <0-65535>",
334 "")
335{
336 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200337 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welted193cb32010-05-17 22:58:03 +0200338 uint16_t port = atoi(argv[1]);
339
340}
341#endif
342
343DEFUN(cfg_ggsn_gtp_version, cfg_ggsn_gtp_version_cmd,
344 "ggsn <0-255> gtp-version (0|1)",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100345 GGSN_STR "GGSN Number\n" "GTP Version\n"
346 "Version 0\n" "Version 1\n")
Harald Welted193cb32010-05-17 22:58:03 +0200347{
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
351 if (atoi(argv[1]))
352 ggc->gtp_version = 1;
353 else
354 ggc->gtp_version = 0;
355
356 return CMD_SUCCESS;
357}
358
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800359DEFUN(cfg_ggsn_dynamic_lookup, cfg_ggsn_dynamic_lookup_cmd,
360 "ggsn dynamic",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100361 GGSN_STR
362 "Enable dynamic resolving of GGSNs based on DNS resolving the APN name like in a GRX-style setup."
363 " Changing this setting requires a restart.\n")
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800364{
365 sgsn->cfg.dynamic_lookup = 1;
366 return CMD_SUCCESS;
367}
368
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800369DEFUN(cfg_grx_ggsn, cfg_grx_ggsn_cmd,
370 "grx-dns-add A.B.C.D",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100371 "Use the specified IP address for DNS-resolving the AP names to GGSN IP addresses\n"
372 "IPv4 address\n")
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800373{
374 struct ares_addr_node *node = talloc_zero(tall_bsc_ctx, struct ares_addr_node);
375 node->family = AF_INET;
376 inet_aton(argv[0], &node->addr.addr4);
377
378 node->next = sgsn->ares_servers;
379 sgsn->ares_servers = node;
380 return CMD_SUCCESS;
381}
382
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100383#define APN_STR "Configure the information per APN\n"
384#define APN_GW_STR "The APN gateway name optionally prefixed by '*' (wildcard)\n"
385
386static int add_apn_ggsn_mapping(struct vty *vty, const char *apn_str,
387 const char *imsi_prefix, int ggsn_id)
388{
389 struct apn_ctx *actx;
390 struct sgsn_ggsn_ctx *ggsn;
391
392 ggsn = sgsn_ggsn_ctx_by_id(ggsn_id);
393 if (ggsn == NULL) {
394 vty_out(vty, "%% a GGSN with id %d has not been defined%s",
395 ggsn_id, VTY_NEWLINE);
396 return CMD_WARNING;
397 }
398
399 actx = sgsn_apn_ctx_find_alloc(apn_str, imsi_prefix);
400 if (!actx) {
401 vty_out(vty, "%% unable to create APN context for %s/%s%s",
402 apn_str, imsi_prefix, VTY_NEWLINE);
403 return CMD_WARNING;
404 }
405
406 actx->ggsn = ggsn;
407
408 return CMD_SUCCESS;
409}
410
Harald Welted193cb32010-05-17 22:58:03 +0200411DEFUN(cfg_apn_ggsn, cfg_apn_ggsn_cmd,
412 "apn APNAME ggsn <0-255>",
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100413 APN_STR APN_GW_STR
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100414 "Select the GGSN to use for the given APN gateway prefix\n"
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100415 "The GGSN id")
Harald Welted193cb32010-05-17 22:58:03 +0200416{
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100417
418 return add_apn_ggsn_mapping(vty, argv[0], "", atoi(argv[1]));
Harald Welted193cb32010-05-17 22:58:03 +0200419}
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100420
421DEFUN(cfg_apn_imsi_ggsn, cfg_apn_imsi_ggsn_cmd,
422 "apn APNAME imsi-prefix IMSIPRE ggsn <0-255>",
423 APN_STR APN_GW_STR
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100424 "Select the GGSN to use for the given APN gateway prefix if and only if the IMSI matches the"
425 " given prefix.\n"
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100426 "An IMSI prefix\n"
427 "Select the GGSN to use when APN gateway and IMSI prefix match\n"
428 "The GGSN id")
429{
430
431 return add_apn_ggsn_mapping(vty, argv[0], argv[1], atoi(argv[2]));
432}
Harald Welted193cb32010-05-17 22:58:03 +0200433
434const struct value_string gprs_mm_st_strs[] = {
435 { GMM_DEREGISTERED, "DEREGISTERED" },
436 { GMM_COMMON_PROC_INIT, "COMMON PROCEDURE (INIT)" },
437 { GMM_REGISTERED_NORMAL, "REGISTERED (NORMAL)" },
Harald Weltebffeff82010-06-09 15:50:45 +0200438 { GMM_REGISTERED_SUSPENDED, "REGISTERED (SUSPENDED)" },
Harald Welted193cb32010-05-17 22:58:03 +0200439 { GMM_DEREGISTERED_INIT, "DEREGISTERED (INIT)" },
440 { 0, NULL }
441};
442
Maxc005db72017-10-27 18:43:29 +0200443char *sgsn_gtp_ntoa(struct ul16_t *ul)
Harald Welte471ac7d2016-12-15 19:48:58 +0100444{
Max8492c202017-12-05 17:28:15 +0100445 struct in_addr ia;
446
447 if (gsna2in_addr(&ia, ul) != 0)
Harald Welte471ac7d2016-12-15 19:48:58 +0100448 return "UNKNOWN";
Max8492c202017-12-05 17:28:15 +0100449
450 return inet_ntoa(ia);
Harald Welte471ac7d2016-12-15 19:48:58 +0100451}
452
Harald Welted193cb32010-05-17 22:58:03 +0200453static void vty_dump_pdp(struct vty *vty, const char *pfx,
454 struct sgsn_pdp_ctx *pdp)
455{
Jacob Erlbeck99985b52014-10-13 10:32:00 +0200456 const char *imsi = pdp->mm ? pdp->mm->imsi : "(detaching)";
Harald Welte471ac7d2016-12-15 19:48:58 +0100457 vty_out(vty, "%sPDP Context IMSI: %s, SAPI: %u, NSAPI: %u, TI: %u%s",
458 pfx, imsi, pdp->sapi, pdp->nsapi, pdp->ti, VTY_NEWLINE);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200459 if (pdp->lib) {
Max7933d962017-10-19 16:52:30 +0200460 char apnbuf[APN_MAXLEN + 1];
Harald Weltedfbd2c82017-08-13 00:56:45 +0200461 vty_out(vty, "%s APN: %s%s", pfx,
Max7933d962017-10-19 16:52:30 +0200462 osmo_apn_to_str(apnbuf, pdp->lib->apn_use.v, pdp->lib->apn_use.l),
Harald Weltedfbd2c82017-08-13 00:56:45 +0200463 VTY_NEWLINE);
464 vty_out(vty, "%s PDP Address: %s%s", pfx,
465 gprs_pdpaddr2str(pdp->lib->eua.v, pdp->lib->eua.l),
466 VTY_NEWLINE);
Maxb24af2b2017-12-05 17:54:42 +0100467 vty_out(vty, "%s GTPv%d Local Control(%s / TEIC: 0x%08x) ", pfx, pdp->lib->version,
Maxc005db72017-10-27 18:43:29 +0200468 sgsn_gtp_ntoa(&pdp->lib->gsnlc), pdp->lib->teic_own);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200469 vty_out(vty, "Data(%s / TEID: 0x%08x)%s",
Maxc005db72017-10-27 18:43:29 +0200470 sgsn_gtp_ntoa(&pdp->lib->gsnlu), pdp->lib->teid_own, VTY_NEWLINE);
Maxb24af2b2017-12-05 17:54:42 +0100471 vty_out(vty, "%s GTPv%d Remote Control(%s / TEIC: 0x%08x) ", pfx, pdp->lib->version,
Maxc005db72017-10-27 18:43:29 +0200472 sgsn_gtp_ntoa(&pdp->lib->gsnrc), pdp->lib->teic_gn);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200473 vty_out(vty, "Data(%s / TEID: 0x%08x)%s",
Maxc005db72017-10-27 18:43:29 +0200474 sgsn_gtp_ntoa(&pdp->lib->gsnru), pdp->lib->teid_gn, VTY_NEWLINE);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200475 }
Harald Welte471ac7d2016-12-15 19:48:58 +0100476
Harald Welteefbdee92010-06-10 00:20:12 +0200477 vty_out_rate_ctr_group(vty, " ", pdp->ctrg);
Harald Welted193cb32010-05-17 22:58:03 +0200478}
479
480static void vty_dump_mmctx(struct vty *vty, const char *pfx,
481 struct sgsn_mm_ctx *mm, int pdp)
482{
483 vty_out(vty, "%sMM Context for IMSI %s, IMEI %s, P-TMSI %08x%s",
484 pfx, mm->imsi, mm->imei, mm->p_tmsi, VTY_NEWLINE);
Holger Hans Peter Freyther8ee13e22015-05-18 10:00:03 +0200485 vty_out(vty, "%s MSISDN: %s, TLLI: %08x%s HLR: %s",
Harald Weltef97ee042015-12-25 19:12:21 +0100486 pfx, mm->msisdn, mm->gb.tlli, mm->hlr, VTY_NEWLINE);
Harald Welted193cb32010-05-17 22:58:03 +0200487 vty_out(vty, "%s MM State: %s, Routeing Area: %u-%u-%u-%u, "
488 "Cell ID: %u%s", pfx,
Alexander Couzens4f8da6d2017-01-31 15:34:26 +0100489 get_value_string(gprs_mm_st_strs, mm->gmm_state),
Harald Welted193cb32010-05-17 22:58:03 +0200490 mm->ra.mcc, mm->ra.mnc, mm->ra.lac, mm->ra.rac,
Harald Weltef97ee042015-12-25 19:12:21 +0100491 mm->gb.cell_id, VTY_NEWLINE);
Harald Welted193cb32010-05-17 22:58:03 +0200492
Harald Welte8acd88f2010-05-18 10:57:45 +0200493 vty_out_rate_ctr_group(vty, " ", mm->ctrg);
494
Harald Welted193cb32010-05-17 22:58:03 +0200495 if (pdp) {
496 struct sgsn_pdp_ctx *pdp;
497
498 llist_for_each_entry(pdp, &mm->pdp_list, list)
499 vty_dump_pdp(vty, " ", pdp);
500 }
501}
502
503DEFUN(show_sgsn, show_sgsn_cmd, "show sgsn",
504 SHOW_STR "Display information about the SGSN")
505{
Jacob Erlbeck80547992014-12-19 19:19:46 +0100506 if (sgsn->gsup_client) {
507 struct ipa_client_conn *link = sgsn->gsup_client->link;
508 vty_out(vty,
509 " Remote authorization: %sconnected to %s:%d via GSUP%s",
510 sgsn->gsup_client->is_connected ? "" : "not ",
511 link->addr, link->port,
512 VTY_NEWLINE);
513 }
Maxbaabc682017-10-20 13:39:57 +0200514 if (sgsn->gsn)
515 vty_out(vty, " GSN: signalling %s, user traffic %s%s",
516 inet_ntoa(sgsn->gsn->gsnc), inet_ntoa(sgsn->gsn->gsnu), VTY_NEWLINE);
517
Harald Welted193cb32010-05-17 22:58:03 +0200518 /* FIXME: statistics */
519 return CMD_SUCCESS;
520}
521
522#define MMCTX_STR "MM Context\n"
523#define INCLUDE_PDP_STR "Include PDP Context Information\n"
524
525#if 0
526DEFUN(show_mmctx_tlli, show_mmctx_tlli_cmd,
527 "show mm-context tlli HEX [pdp]",
528 SHOW_STR MMCTX_STR "Identify by TLLI\n" "TLLI\n" INCLUDE_PDP_STR)
529{
530 uint32_t tlli;
531 struct sgsn_mm_ctx *mm;
532
533 tlli = strtoul(argv[0], NULL, 16);
534 mm = sgsn_mm_ctx_by_tlli(tlli);
535 if (!mm) {
536 vty_out(vty, "No MM context for TLLI %08x%s",
537 tlli, VTY_NEWLINE);
538 return CMD_WARNING;
539 }
540 vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
541 return CMD_SUCCESS;
542}
543#endif
544
545DEFUN(swow_mmctx_imsi, show_mmctx_imsi_cmd,
546 "show mm-context imsi IMSI [pdp]",
547 SHOW_STR MMCTX_STR "Identify by IMSI\n" "IMSI of the MM Context\n"
548 INCLUDE_PDP_STR)
549{
550 struct sgsn_mm_ctx *mm;
551
552 mm = sgsn_mm_ctx_by_imsi(argv[0]);
553 if (!mm) {
554 vty_out(vty, "No MM context for IMSI %s%s",
555 argv[0], VTY_NEWLINE);
556 return CMD_WARNING;
557 }
558 vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
559 return CMD_SUCCESS;
560}
561
562DEFUN(swow_mmctx_all, show_mmctx_all_cmd,
563 "show mm-context all [pdp]",
564 SHOW_STR MMCTX_STR "All MM Contexts\n" INCLUDE_PDP_STR)
565{
566 struct sgsn_mm_ctx *mm;
567
568 llist_for_each_entry(mm, &sgsn_mm_ctxts, list)
569 vty_dump_mmctx(vty, "", mm, argv[0] ? 1 : 0);
570
571 return CMD_SUCCESS;
572}
573
Harald Welted193cb32010-05-17 22:58:03 +0200574DEFUN(show_pdpctx_all, show_pdpctx_all_cmd,
575 "show pdp-context all",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100576 SHOW_STR "Display information on PDP Context\n" "Show everything\n")
Harald Welted193cb32010-05-17 22:58:03 +0200577{
578 struct sgsn_pdp_ctx *pdp;
579
580 llist_for_each_entry(pdp, &sgsn_pdp_ctxts, g_list)
581 vty_dump_pdp(vty, "", pdp);
582
583 return CMD_SUCCESS;
584}
Harald Welte288be162010-05-01 16:48:27 +0200585
Harald Welte7f6da482013-03-19 11:00:13 +0100586
587DEFUN(imsi_acl, cfg_imsi_acl_cmd,
588 "imsi-acl (add|del) IMSI",
589 "Access Control List of foreign IMSIs\n"
590 "Add IMSI to ACL\n"
591 "Remove IMSI from ACL\n"
592 "IMSI of subscriber\n")
593{
Philipp Maier6ee49d82017-02-28 16:53:07 +0100594 char imsi_sanitized[GSM23003_IMSI_MAX_DIGITS+1];
Harald Welte7f6da482013-03-19 11:00:13 +0100595 const char *op = argv[0];
Philipp Maier6ee49d82017-02-28 16:53:07 +0100596 const char *imsi = imsi_sanitized;
Harald Welte7f6da482013-03-19 11:00:13 +0100597 int rc;
598
Philipp Maier6ee49d82017-02-28 16:53:07 +0100599 /* Sanitize IMSI */
600 if (strlen(argv[1]) > GSM23003_IMSI_MAX_DIGITS) {
601 vty_out(vty, "%% IMSI (%s) too long -- ignored!%s",
602 argv[1], VTY_NEWLINE);
603 return CMD_WARNING;
604 }
605 memset(imsi_sanitized, '0', sizeof(imsi_sanitized));
606 strcpy(imsi_sanitized+GSM23003_IMSI_MAX_DIGITS-strlen(argv[1]),argv[1]);
607
Harald Welte7f6da482013-03-19 11:00:13 +0100608 if (!strcmp(op, "add"))
Jacob Erlbeck3b5d4072014-10-24 15:11:03 +0200609 rc = sgsn_acl_add(imsi, g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +0100610 else
Jacob Erlbeck3b5d4072014-10-24 15:11:03 +0200611 rc = sgsn_acl_del(imsi, g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +0100612
613 if (rc < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100614 vty_out(vty, "%% unable to %s ACL%s", op, VTY_NEWLINE);
Harald Welte7f6da482013-03-19 11:00:13 +0100615 return CMD_WARNING;
616 }
617
618 return CMD_SUCCESS;
619}
620
Max93408ae2016-06-28 14:10:16 +0200621DEFUN(cfg_encrypt, cfg_encrypt_cmd,
622 "encryption (GEA0|GEA1|GEA2|GEA3|GEA4)",
623 "Set encryption algorithm for SGSN\n"
624 "Use GEA0 (no encryption)\n"
625 "Use GEA1\nUse GEA2\nUse GEA3\nUse GEA4\n")
626{
Max93408ae2016-06-28 14:10:16 +0200627 enum gprs_ciph_algo c = get_string_value(gprs_cipher_names, argv[0]);
Max086067f2017-05-02 13:03:28 +0200628 if (c != GPRS_ALGO_GEA0) {
629 if (!gprs_cipher_supported(c)) {
630 vty_out(vty, "%% cipher %s is unsupported in current version%s", argv[0], VTY_NEWLINE);
631 return CMD_WARNING;
632 }
633
634 if (!g_cfg->require_authentication) {
635 vty_out(vty, "%% unable to use encryption %s without authentication: please adjust auth-policy%s",
636 argv[0], VTY_NEWLINE);
637 return CMD_WARNING;
638 }
Max93408ae2016-06-28 14:10:16 +0200639 }
640
641 g_cfg->cipher = c;
642
643 return CMD_SUCCESS;
644}
645
Harald Welte3dfb5492013-03-19 11:48:54 +0100646DEFUN(cfg_auth_policy, cfg_auth_policy_cmd,
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100647 "auth-policy (accept-all|closed|acl-only|remote)",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +0100648 "Configure the Authorization policy of the SGSN. This setting determines which subscribers are"
649 " permitted to register to the network.\n"
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100650 "Accept all IMSIs (DANGEROUS)\n"
651 "Accept only home network subscribers or those in the ACL\n"
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100652 "Accept only subscribers in the ACL\n"
653 "Use remote subscription data only (HLR)\n")
Harald Welte3dfb5492013-03-19 11:48:54 +0100654{
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100655 int val = get_string_value(sgsn_auth_pol_strs, argv[0]);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100656 OSMO_ASSERT(val >= SGSN_AUTH_POLICY_OPEN && val <= SGSN_AUTH_POLICY_REMOTE);
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100657 g_cfg->auth_policy = val;
Jacob Erlbeck9d4f46c2014-12-17 13:20:08 +0100658 g_cfg->require_authentication = (val == SGSN_AUTH_POLICY_REMOTE);
Jacob Erlbeck771573c2014-12-19 18:08:48 +0100659 g_cfg->require_update_location = (val == SGSN_AUTH_POLICY_REMOTE);
Harald Welte3dfb5492013-03-19 11:48:54 +0100660
661 return CMD_SUCCESS;
662}
663
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100664/* Subscriber */
Neels Hofmeyr396f2e62017-09-04 15:13:25 +0200665#include <osmocom/sgsn/gprs_subscriber.h>
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100666
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100667static void subscr_dump_full_vty(struct vty *vty, struct gprs_subscr *gsub, int pending)
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100668{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100669#if 0
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100670 char expire_time[200];
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100671#endif
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100672 struct gsm_auth_tuple *at;
673 int at_idx;
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100674 struct sgsn_subscriber_pdp_data *pdp;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100675
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100676 vty_out(vty, " Authorized: %d%s",
677 gsub->authorized, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100678 vty_out(vty, " LAC: %d/0x%x%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100679 gsub->lac, gsub->lac, VTY_NEWLINE);
680 vty_out(vty, " IMSI: %s%s", gsub->imsi, VTY_NEWLINE);
681 if (gsub->tmsi != GSM_RESERVED_TMSI)
682 vty_out(vty, " TMSI: %08X%s", gsub->tmsi,
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100683 VTY_NEWLINE);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100684 if (gsub->sgsn_data->msisdn_len > 0)
Holger Hans Peter Freytherf7b38262015-04-23 16:58:33 -0400685 vty_out(vty, " MSISDN (BCD): %s%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100686 osmo_hexdump(gsub->sgsn_data->msisdn,
687 gsub->sgsn_data->msisdn_len),
Holger Hans Peter Freytherf7b38262015-04-23 16:58:33 -0400688 VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100689
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100690 if (strlen(gsub->imei) > 0)
691 vty_out(vty, " IMEI: %s%s", gsub->imei, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100692
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100693 for (at_idx = 0; at_idx < ARRAY_SIZE(gsub->sgsn_data->auth_triplets);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100694 at_idx++) {
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100695 at = &gsub->sgsn_data->auth_triplets[at_idx];
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100696 if (at->key_seq == GSM_KEY_SEQ_INVAL)
697 continue;
698
699 vty_out(vty, " A3A8 tuple (used %d times): ",
700 at->use_count);
Harald Welte89837d42016-05-06 23:28:11 +0200701 vty_out(vty, " CKSN: %d, ",
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100702 at->key_seq);
Harald Welte89837d42016-05-06 23:28:11 +0200703 if (at->vec.auth_types & OSMO_AUTH_TYPE_GSM) {
704 vty_out(vty, "RAND: %s, ",
705 osmo_hexdump(at->vec.rand,
706 sizeof(at->vec.rand)));
707 vty_out(vty, "SRES: %s, ",
708 osmo_hexdump(at->vec.sres,
709 sizeof(at->vec.sres)));
710 vty_out(vty, "Kc: %s%s",
711 osmo_hexdump(at->vec.kc,
712 sizeof(at->vec.kc)), VTY_NEWLINE);
713 }
714 if (at->vec.auth_types & OSMO_AUTH_TYPE_UMTS) {
715 vty_out(vty, " AUTN: %s, ",
716 osmo_hexdump(at->vec.autn,
717 sizeof(at->vec.autn)));
718 vty_out(vty, "RES: %s, ",
719 osmo_hexdump(at->vec.res, at->vec.res_len));
720 vty_out(vty, "IK: %s, ",
721 osmo_hexdump(at->vec.ik, sizeof(at->vec.ik)));
722 vty_out(vty, "CK: %s, ",
723 osmo_hexdump(at->vec.ck, sizeof(at->vec.ck)));
724 }
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100725 }
726
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100727 llist_for_each_entry(pdp, &gsub->sgsn_data->pdp_list, list) {
Holger Hans Peter Freytherd05e0692015-04-23 16:59:04 -0400728 vty_out(vty, " PDP info: Id: %d, Type: 0x%04x, APN: '%s' QoS: %s%s",
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100729 pdp->context_id, pdp->pdp_type, pdp->apn_str,
Holger Hans Peter Freytherd05e0692015-04-23 16:59:04 -0400730 osmo_hexdump(pdp->qos_subscribed, pdp->qos_subscribed_len),
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100731 VTY_NEWLINE);
732 }
733
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100734#if 0
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100735 /* print the expiration time of a subscriber */
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100736 if (gsub->expire_lu) {
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100737 strftime(expire_time, sizeof(expire_time),
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100738 "%a, %d %b %Y %T %z", localtime(&gsub->expire_lu));
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100739 expire_time[sizeof(expire_time) - 1] = '\0';
740 vty_out(vty, " Expiration Time: %s%s", expire_time, VTY_NEWLINE);
741 }
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100742#endif
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100743
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100744 if (gsub->flags)
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100745 vty_out(vty, " Flags: %s%s%s%s%s%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100746 gsub->flags & GPRS_SUBSCRIBER_FIRST_CONTACT ?
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100747 "FIRST_CONTACT " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100748 gsub->flags & GPRS_SUBSCRIBER_CANCELLED ?
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100749 "CANCELLED " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100750 gsub->flags & GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING ?
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100751 "UPDATE_LOCATION_PENDING " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100752 gsub->flags & GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING ?
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100753 "AUTH_INFO_PENDING " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100754 gsub->flags & GPRS_SUBSCRIBER_ENABLE_PURGE ?
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100755 "ENABLE_PURGE " : "",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100756 VTY_NEWLINE);
757
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100758 vty_out(vty, " Use count: %u%s", gsub->use_count, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100759}
760
761DEFUN(show_subscr_cache,
762 show_subscr_cache_cmd,
763 "show subscriber cache",
764 SHOW_STR "Show information about subscribers\n"
765 "Display contents of subscriber cache\n")
766{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100767 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100768
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100769 llist_for_each_entry(subscr, gprs_subscribers, entry) {
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100770 vty_out(vty, " Subscriber:%s", VTY_NEWLINE);
771 subscr_dump_full_vty(vty, subscr, 0);
772 }
773
774 return CMD_SUCCESS;
775}
776
777#define UPDATE_SUBSCR_STR "update-subscriber imsi IMSI "
778#define UPDATE_SUBSCR_HELP "Update subscriber list\n" \
779 "Use the IMSI to select the subscriber\n" \
780 "The IMSI\n"
781
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100782#define UPDATE_SUBSCR_INSERT_HELP "Insert data into the subscriber record\n"
783
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100784DEFUN(update_subscr_insert_auth_triplet, update_subscr_insert_auth_triplet_cmd,
785 UPDATE_SUBSCR_STR "insert auth-triplet <1-5> sres SRES rand RAND kc KC",
786 UPDATE_SUBSCR_HELP
787 UPDATE_SUBSCR_INSERT_HELP
788 "Update authentication triplet\n"
789 "Triplet index\n"
790 "Set SRES value\nSRES value (4 byte) in hex\n"
791 "Set RAND value\nRAND value (16 byte) in hex\n"
792 "Set Kc value\nKc value (8 byte) in hex\n")
793{
794 const char *imsi = argv[0];
795 const int cksn = atoi(argv[1]) - 1;
796 const char *sres_str = argv[2];
797 const char *rand_str = argv[3];
798 const char *kc_str = argv[4];
799 struct gsm_auth_tuple at = {0,};
800
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100801 struct gprs_subscr *subscr;
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100802
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100803 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100804 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100805 vty_out(vty, "%% unable get subscriber record for %s%s",
806 imsi, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100807 return CMD_WARNING;
808 }
809
810 OSMO_ASSERT(subscr->sgsn_data);
811
Harald Welte121e9a42016-04-20 13:13:19 +0200812 if (osmo_hexparse(sres_str, &at.vec.sres[0], sizeof(at.vec.sres)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100813 vty_out(vty, "%% invalid SRES value '%s'%s",
814 sres_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100815 goto failed;
816 }
Harald Welte121e9a42016-04-20 13:13:19 +0200817 if (osmo_hexparse(rand_str, &at.vec.rand[0], sizeof(at.vec.rand)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100818 vty_out(vty, "%% invalid RAND value '%s'%s",
819 rand_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100820 goto failed;
821 }
Harald Welte121e9a42016-04-20 13:13:19 +0200822 if (osmo_hexparse(kc_str, &at.vec.kc[0], sizeof(at.vec.kc)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100823 vty_out(vty, "%% invalid Kc value '%s'%s",
824 kc_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100825 goto failed;
826 }
827 at.key_seq = cksn;
828
829 subscr->sgsn_data->auth_triplets[cksn] = at;
830 subscr->sgsn_data->auth_triplets_updated = 1;
831
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100832 gprs_subscr_put(subscr);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100833
834 return CMD_SUCCESS;
835
836failed:
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100837 gprs_subscr_put(subscr);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100838 return CMD_SUCCESS;
839}
840
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100841DEFUN(update_subscr_cancel, update_subscr_cancel_cmd,
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100842 UPDATE_SUBSCR_STR "cancel (update-procedure|subscription-withdraw)",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100843 UPDATE_SUBSCR_HELP
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100844 "Cancel (remove) subscriber record\n"
845 "The MS moved to another SGSN\n"
846 "The subscription is no longer valid\n")
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100847{
848 const char *imsi = argv[0];
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100849 const char *cancel_type = argv[1];
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100850
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100851 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100852
853 subscr = gprs_subscr_get_by_imsi(imsi);
854 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100855 vty_out(vty, "%% no subscriber record for %s%s",
856 imsi, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100857 return CMD_WARNING;
858 }
859
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100860 if (strcmp(cancel_type, "update-procedure") == 0)
861 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
862 else
863 subscr->sgsn_data->error_cause = GMM_CAUSE_IMPL_DETACHED;
864
Jacob Erlbeck37139e52015-01-23 13:52:55 +0100865 gprs_subscr_cancel(subscr);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100866 gprs_subscr_put(subscr);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100867
868 return CMD_SUCCESS;
869}
870
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100871DEFUN(update_subscr_create, update_subscr_create_cmd,
872 UPDATE_SUBSCR_STR "create",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100873 UPDATE_SUBSCR_HELP
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100874 "Create a subscriber entry\n")
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100875{
876 const char *imsi = argv[0];
877
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100878 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100879
880 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100881 if (subscr) {
882 vty_out(vty, "%% subscriber record already exists for %s%s",
883 imsi, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100884 return CMD_WARNING;
885 }
886
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100887 subscr = gprs_subscr_get_or_create(imsi);
888 subscr->keep_in_ram = 1;
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100889 gprs_subscr_put(subscr);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100890
891 return CMD_SUCCESS;
892}
893
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100894DEFUN(update_subscr_destroy, update_subscr_destroy_cmd,
895 UPDATE_SUBSCR_STR "destroy",
896 UPDATE_SUBSCR_HELP
897 "Destroy a subscriber entry\n")
898{
899 const char *imsi = argv[0];
900
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100901 struct gprs_subscr *subscr;
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100902
903 subscr = gprs_subscr_get_by_imsi(imsi);
904 if (!subscr) {
905 vty_out(vty, "%% subscriber record does not exist for %s%s",
906 imsi, VTY_NEWLINE);
907 return CMD_WARNING;
908 }
909
910 subscr->keep_in_ram = 0;
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100911 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100912 gprs_subscr_cancel(subscr);
913 if (subscr->use_count > 1)
914 vty_out(vty, "%% subscriber is still in use%s",
915 VTY_NEWLINE);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100916 gprs_subscr_put(subscr);
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100917
918 return CMD_SUCCESS;
919}
920
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100921#define UL_ERR_STR "system-failure|data-missing|unexpected-data-value|" \
922 "unknown-subscriber|roaming-not-allowed"
923
924#define UL_ERR_HELP \
925 "Force error code SystemFailure\n" \
926 "Force error code DataMissing\n" \
927 "Force error code UnexpectedDataValue\n" \
928 "Force error code UnknownSubscriber\n" \
929 "Force error code RoamingNotAllowed\n"
930
931DEFUN(update_subscr_update_location_result, update_subscr_update_location_result_cmd,
932 UPDATE_SUBSCR_STR "update-location-result (ok|" UL_ERR_STR ")",
933 UPDATE_SUBSCR_HELP
934 "Complete the update location procedure\n"
935 "The update location request succeeded\n"
936 UL_ERR_HELP)
937{
938 const char *imsi = argv[0];
939 const char *ret_code_str = argv[1];
940
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100941 struct gprs_subscr *subscr;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100942
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100943 const struct value_string cause_mapping[] = {
944 { GMM_CAUSE_NET_FAIL, "system-failure" },
945 { GMM_CAUSE_INV_MAND_INFO, "data-missing" },
946 { GMM_CAUSE_PROTO_ERR_UNSPEC, "unexpected-data-value" },
947 { GMM_CAUSE_IMSI_UNKNOWN, "unknown-subscriber" },
948 { GMM_CAUSE_GPRS_NOTALLOWED, "roaming-not-allowed" },
949 { 0, NULL }
950 };
951
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100952 subscr = gprs_subscr_get_by_imsi(imsi);
953 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100954 vty_out(vty, "%% unable to get subscriber record for %s%s",
955 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100956 return CMD_WARNING;
957 }
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100958
959 if (strcmp(ret_code_str, "ok") == 0) {
960 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100961 subscr->authorized = 1;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100962 } else {
963 subscr->sgsn_data->error_cause =
964 get_string_value(cause_mapping, ret_code_str);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100965 subscr->authorized = 0;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100966 }
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100967
968 gprs_subscr_update(subscr);
969
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100970 gprs_subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100971
972 return CMD_SUCCESS;
973}
974
975DEFUN(update_subscr_update_auth_info, update_subscr_update_auth_info_cmd,
976 UPDATE_SUBSCR_STR "update-auth-info",
977 UPDATE_SUBSCR_HELP
978 "Complete the send authentication info procedure\n")
979{
980 const char *imsi = argv[0];
981
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100982 struct gprs_subscr *subscr;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100983
984 subscr = gprs_subscr_get_by_imsi(imsi);
985 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100986 vty_out(vty, "%% unable to get subscriber record for %s%s",
987 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100988 return CMD_WARNING;
989 }
990
991 gprs_subscr_update_auth_info(subscr);
992
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100993 gprs_subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100994
995 return CMD_SUCCESS;
996}
997
Jacob Erlbeck39f040d2014-12-18 12:46:47 +0100998DEFUN(cfg_gsup_remote_ip, cfg_gsup_remote_ip_cmd,
999 "gsup remote-ip A.B.C.D",
1000 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001001 "Set the IP address of the remote GSUP server (e.g. OsmoHLR)."
1002 " This setting only applies if 'auth-policy remote' is used.\n"
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001003 "IPv4 Address\n")
1004{
1005 inet_aton(argv[0], &g_cfg->gsup_server_addr.sin_addr);
1006
1007 return CMD_SUCCESS;
1008}
1009
1010DEFUN(cfg_gsup_remote_port, cfg_gsup_remote_port_cmd,
1011 "gsup remote-port <0-65535>",
1012 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001013 "Set the TCP port of the remote GSUP server, see also 'gsup remote-ip'\n"
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001014 "Remote TCP port\n")
1015{
1016 g_cfg->gsup_server_port = atoi(argv[0]);
1017
1018 return CMD_SUCCESS;
1019}
1020
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001021DEFUN(cfg_gsup_oap_id, cfg_gsup_oap_id_cmd,
1022 "gsup oap-id <0-65535>",
1023 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001024 "Set the OAP client ID for authentication on the GSUP protocol."
1025 " This setting only applies if 'auth-policy remote' is used.\n"
1026 "OAP client ID (0 == disabled)\n")
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001027{
1028 /* VTY ensures range */
1029 g_cfg->oap.client_id = (uint16_t)atoi(argv[0]);
1030 return CMD_SUCCESS;
1031}
1032
1033DEFUN(cfg_gsup_oap_k, cfg_gsup_oap_k_cmd,
1034 "gsup oap-k K",
1035 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001036 "Set the OAP shared secret key K for authentication on the GSUP protocol."
1037 " This setting only applies if auth-policy remote is used.\n"
1038 "K value (16 byte) hex\n")
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001039{
1040 const char *k = argv[0];
1041
1042 g_cfg->oap.secret_k_present = 0;
1043
1044 if ((!k) || (strlen(k) == 0))
1045 goto disable;
1046
1047 int k_len = osmo_hexparse(k,
1048 g_cfg->oap.secret_k,
1049 sizeof(g_cfg->oap.secret_k));
1050 if (k_len != 16) {
1051 vty_out(vty, "%% need exactly 16 octets for oap-k, got %d.%s",
1052 k_len, VTY_NEWLINE);
1053 goto disable;
1054 }
1055
1056 g_cfg->oap.secret_k_present = 1;
1057 return CMD_SUCCESS;
1058
1059disable:
1060 if (g_cfg->oap.client_id > 0) {
1061 vty_out(vty, "%% OAP client ID set, but invalid oap-k value disables OAP.%s",
1062 VTY_NEWLINE);
1063 return CMD_WARNING;
1064 }
1065 return CMD_SUCCESS;
1066}
1067
1068DEFUN(cfg_gsup_oap_opc, cfg_gsup_oap_opc_cmd,
1069 "gsup oap-opc OPC",
1070 "GSUP Parameters\n"
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001071 "Set the OAP shared secret OPC for authentication on the GSUP protocol."
1072 " This setting only applies if auth-policy remote is used.\n"
1073 "OPC value (16 byte) hex\n")
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001074{
1075 const char *opc = argv[0];
1076
1077 g_cfg->oap.secret_opc_present = 0;
1078
1079 if ((!opc) || (strlen(opc) == 0))
1080 goto disable;
1081
1082 int opc_len = osmo_hexparse(opc,
1083 g_cfg->oap.secret_opc,
1084 sizeof(g_cfg->oap.secret_opc));
1085 if (opc_len != 16) {
1086 vty_out(vty, "%% need exactly 16 octets for oap-opc, got %d.%s",
1087 opc_len, VTY_NEWLINE);
1088 goto disable;
1089 }
1090
1091 g_cfg->oap.secret_opc_present = 1;
1092 return CMD_SUCCESS;
1093
1094disable:
1095 if (g_cfg->oap.client_id > 0) {
1096 vty_out(vty, "%% OAP client ID set, but invalid oap-opc value disables OAP.%s",
1097 VTY_NEWLINE);
1098 return CMD_WARNING;
1099 }
1100 return CMD_SUCCESS;
1101}
1102
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001103DEFUN(cfg_apn_name, cfg_apn_name_cmd,
1104 "access-point-name NAME",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001105 "Globally allow the given APN name for all subscribers.\n"
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001106 "Add this NAME to the list\n")
1107{
1108 return add_apn_ggsn_mapping(vty, argv[0], "", 0);
1109}
1110
1111DEFUN(cfg_no_apn_name, cfg_no_apn_name_cmd,
1112 "no access-point-name NAME",
1113 NO_STR "Configure a global list of allowed APNs\n"
1114 "Remove entry with NAME\n")
1115{
1116 struct apn_ctx *apn_ctx = sgsn_apn_ctx_by_name(argv[0], "");
1117 if (!apn_ctx)
1118 return CMD_SUCCESS;
1119
1120 sgsn_apn_ctx_free(apn_ctx);
1121 return CMD_SUCCESS;
1122}
1123
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001124DEFUN(cfg_cdr_filename, cfg_cdr_filename_cmd,
1125 "cdr filename NAME",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001126 "CDR\n"
1127 "Set the file name for the call-data-record file, logging the data usage of each subscriber.\n"
1128 "filename\n")
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001129{
1130 talloc_free(g_cfg->cdr.filename);
1131 g_cfg->cdr.filename = talloc_strdup(tall_vty_ctx, argv[0]);
1132 return CMD_SUCCESS;
1133}
1134
1135DEFUN(cfg_no_cdr_filename, cfg_no_cdr_filename_cmd,
1136 "no cdr filename",
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +01001137 NO_STR "CDR\nDisable saving CDR to file\n")
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001138{
1139 talloc_free(g_cfg->cdr.filename);
1140 g_cfg->cdr.filename = NULL;
1141 return CMD_SUCCESS;
1142}
1143
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +01001144DEFUN(cfg_cdr_trap, cfg_cdr_trap_cmd,
1145 "cdr trap",
1146 "CDR\nEnable sending CDR via TRAP CTRL messages\n")
1147{
1148 g_cfg->cdr.trap = true;
1149 return CMD_SUCCESS;
1150}
1151
1152DEFUN(cfg_no_cdr_trap, cfg_no_cdr_trap_cmd,
1153 "no cdr trap",
1154 NO_STR "CDR\nDisable sending CDR via TRAP CTRL messages\n")
1155{
1156 g_cfg->cdr.trap = false;
1157 return CMD_SUCCESS;
1158}
1159
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001160DEFUN(cfg_cdr_interval, cfg_cdr_interval_cmd,
1161 "cdr interval <1-2147483647>",
Neels Hofmeyr24bb7472018-03-06 16:14:26 +01001162 "CDR\n"
1163 "Set the interval for the call-data-record file\n"
1164 "interval in seconds\n")
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001165{
1166 g_cfg->cdr.interval = atoi(argv[0]);
1167 return CMD_SUCCESS;
1168}
1169
Philippf1f34362016-08-26 17:00:21 +02001170#define COMPRESSION_STR "Configure compression\n"
1171DEFUN(cfg_no_comp_rfc1144, cfg_no_comp_rfc1144_cmd,
1172 "no compression rfc1144",
1173 NO_STR COMPRESSION_STR "disable rfc1144 TCP/IP header compression\n")
1174{
1175 g_cfg->pcomp_rfc1144.active = 0;
1176 g_cfg->pcomp_rfc1144.passive = 0;
1177 return CMD_SUCCESS;
1178}
1179
1180DEFUN(cfg_comp_rfc1144, cfg_comp_rfc1144_cmd,
1181 "compression rfc1144 active slots <1-256>",
1182 COMPRESSION_STR
1183 "RFC1144 Header compresion scheme\n"
1184 "Compression is actively proposed\n"
1185 "Number of compression state slots\n"
1186 "Number of compression state slots\n")
1187{
1188 g_cfg->pcomp_rfc1144.active = 1;
1189 g_cfg->pcomp_rfc1144.passive = 1;
1190 g_cfg->pcomp_rfc1144.s01 = atoi(argv[0]) - 1;
1191 return CMD_SUCCESS;
1192}
1193
1194DEFUN(cfg_comp_rfc1144p, cfg_comp_rfc1144p_cmd,
1195 "compression rfc1144 passive",
1196 COMPRESSION_STR
1197 "RFC1144 Header compresion scheme\n"
1198 "Compression is available on request\n")
1199{
1200 g_cfg->pcomp_rfc1144.active = 0;
1201 g_cfg->pcomp_rfc1144.passive = 1;
1202 return CMD_SUCCESS;
1203}
1204
Philipp73f83d52016-09-02 13:38:01 +02001205DEFUN(cfg_no_comp_v42bis, cfg_no_comp_v42bis_cmd,
1206 "no compression v42bis",
1207 NO_STR COMPRESSION_STR "disable V.42bis data compression\n")
1208{
1209 g_cfg->dcomp_v42bis.active = 0;
1210 g_cfg->dcomp_v42bis.passive = 0;
1211 return CMD_SUCCESS;
1212}
1213
1214DEFUN(cfg_comp_v42bis, cfg_comp_v42bis_cmd,
1215 "compression v42bis active direction (ms|sgsn|both) codewords <512-65535> strlen <6-250>",
1216 COMPRESSION_STR
1217 "V.42bis data compresion scheme\n"
1218 "Compression is actively proposed\n"
1219 "Direction in which the compression shall be active (p0)\n"
1220 "Compress ms->sgsn direction only\n"
1221 "Compress sgsn->ms direction only\n"
1222 "Both directions\n"
1223 "Number of codewords (p1)\n"
1224 "Number of codewords\n"
1225 "Maximum string length (p2)\n" "Maximum string length\n")
1226{
1227 g_cfg->dcomp_v42bis.active = 1;
1228 g_cfg->dcomp_v42bis.passive = 1;
1229
1230 switch (argv[0][0]) {
1231 case 'm':
1232 g_cfg->dcomp_v42bis.p0 = 1;
1233 break;
1234 case 's':
1235 g_cfg->dcomp_v42bis.p0 = 2;
1236 break;
1237 case 'b':
1238 g_cfg->dcomp_v42bis.p0 = 3;
1239 break;
1240 }
1241
1242 g_cfg->dcomp_v42bis.p1 = atoi(argv[1]);
1243 g_cfg->dcomp_v42bis.p2 = atoi(argv[2]);
1244 return CMD_SUCCESS;
1245}
1246
1247DEFUN(cfg_comp_v42bisp, cfg_comp_v42bisp_cmd,
1248 "compression v42bis passive",
1249 COMPRESSION_STR
1250 "V.42bis data compresion scheme\n"
1251 "Compression is available on request\n")
1252{
1253 g_cfg->dcomp_v42bis.active = 0;
1254 g_cfg->dcomp_v42bis.passive = 1;
1255 return CMD_SUCCESS;
1256}
1257
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001258int sgsn_vty_init(struct sgsn_config *cfg)
Harald Welte288be162010-05-01 16:48:27 +02001259{
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001260 g_cfg = cfg;
1261
Harald Welted193cb32010-05-17 22:58:03 +02001262 install_element_ve(&show_sgsn_cmd);
1263 //install_element_ve(&show_mmctx_tlli_cmd);
1264 install_element_ve(&show_mmctx_imsi_cmd);
1265 install_element_ve(&show_mmctx_all_cmd);
1266 install_element_ve(&show_pdpctx_all_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001267 install_element_ve(&show_subscr_cache_cmd);
1268
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01001269 install_element(ENABLE_NODE, &update_subscr_insert_auth_triplet_cmd);
Jacob Erlbeckd9193432015-01-19 14:11:46 +01001270 install_element(ENABLE_NODE, &update_subscr_create_cmd);
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001271 install_element(ENABLE_NODE, &update_subscr_destroy_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001272 install_element(ENABLE_NODE, &update_subscr_cancel_cmd);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001273 install_element(ENABLE_NODE, &update_subscr_update_location_result_cmd);
1274 install_element(ENABLE_NODE, &update_subscr_update_auth_info_cmd);
Harald Welte288be162010-05-01 16:48:27 +02001275
1276 install_element(CONFIG_NODE, &cfg_sgsn_cmd);
1277 install_node(&sgsn_node, config_write_sgsn);
Harald Weltee300d002010-06-02 12:41:34 +02001278 install_element(SGSN_NODE, &cfg_sgsn_bind_addr_cmd);
Harald Welted193cb32010-05-17 22:58:03 +02001279 install_element(SGSN_NODE, &cfg_ggsn_remote_ip_cmd);
1280 //install_element(SGSN_NODE, &cfg_ggsn_remote_port_cmd);
1281 install_element(SGSN_NODE, &cfg_ggsn_gtp_version_cmd);
Harald Welte7f6da482013-03-19 11:00:13 +01001282 install_element(SGSN_NODE, &cfg_imsi_acl_cmd);
Harald Welte3dfb5492013-03-19 11:48:54 +01001283 install_element(SGSN_NODE, &cfg_auth_policy_cmd);
Max93408ae2016-06-28 14:10:16 +02001284 install_element(SGSN_NODE, &cfg_encrypt_cmd);
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001285 install_element(SGSN_NODE, &cfg_gsup_remote_ip_cmd);
1286 install_element(SGSN_NODE, &cfg_gsup_remote_port_cmd);
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001287 install_element(SGSN_NODE, &cfg_gsup_oap_id_cmd);
1288 install_element(SGSN_NODE, &cfg_gsup_oap_k_cmd);
1289 install_element(SGSN_NODE, &cfg_gsup_oap_opc_cmd);
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +01001290 install_element(SGSN_NODE, &cfg_apn_ggsn_cmd);
1291 install_element(SGSN_NODE, &cfg_apn_imsi_ggsn_cmd);
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001292 install_element(SGSN_NODE, &cfg_apn_name_cmd);
1293 install_element(SGSN_NODE, &cfg_no_apn_name_cmd);
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001294 install_element(SGSN_NODE, &cfg_cdr_filename_cmd);
1295 install_element(SGSN_NODE, &cfg_no_cdr_filename_cmd);
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +01001296 install_element(SGSN_NODE, &cfg_cdr_trap_cmd);
1297 install_element(SGSN_NODE, &cfg_no_cdr_trap_cmd);
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001298 install_element(SGSN_NODE, &cfg_cdr_interval_cmd);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001299 install_element(SGSN_NODE, &cfg_ggsn_dynamic_lookup_cmd);
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +08001300 install_element(SGSN_NODE, &cfg_grx_ggsn_cmd);
Harald Welte288be162010-05-01 16:48:27 +02001301
Harald Welte94508822015-08-15 19:08:21 +02001302 install_element(SGSN_NODE, &cfg_sgsn_T3312_cmd);
1303 install_element(SGSN_NODE, &cfg_sgsn_T3322_cmd);
1304 install_element(SGSN_NODE, &cfg_sgsn_T3350_cmd);
1305 install_element(SGSN_NODE, &cfg_sgsn_T3360_cmd);
1306 install_element(SGSN_NODE, &cfg_sgsn_T3370_cmd);
1307 install_element(SGSN_NODE, &cfg_sgsn_T3313_cmd);
1308 install_element(SGSN_NODE, &cfg_sgsn_T3314_cmd);
1309 install_element(SGSN_NODE, &cfg_sgsn_T3316_cmd);
1310 install_element(SGSN_NODE, &cfg_sgsn_T3385_cmd);
1311 install_element(SGSN_NODE, &cfg_sgsn_T3386_cmd);
1312 install_element(SGSN_NODE, &cfg_sgsn_T3395_cmd);
1313 install_element(SGSN_NODE, &cfg_sgsn_T3397_cmd);
1314
Philippf1f34362016-08-26 17:00:21 +02001315 install_element(SGSN_NODE, &cfg_no_comp_rfc1144_cmd);
1316 install_element(SGSN_NODE, &cfg_comp_rfc1144_cmd);
1317 install_element(SGSN_NODE, &cfg_comp_rfc1144p_cmd);
Philipp73f83d52016-09-02 13:38:01 +02001318 install_element(SGSN_NODE, &cfg_no_comp_v42bis_cmd);
1319 install_element(SGSN_NODE, &cfg_comp_v42bis_cmd);
1320 install_element(SGSN_NODE, &cfg_comp_v42bisp_cmd);
Neels Hofmeyr2188a772016-05-20 21:59:55 +02001321
1322#ifdef BUILD_IU
Neels Hofmeyra7a39472017-07-05 15:19:52 +02001323 ranap_iu_vty_init(SGSN_NODE, &g_cfg->iu.rab_assign_addr_enc);
Neels Hofmeyr2188a772016-05-20 21:59:55 +02001324#endif
Harald Welte288be162010-05-01 16:48:27 +02001325 return 0;
1326}
1327
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001328int sgsn_parse_config(const char *config_file)
Harald Welte288be162010-05-01 16:48:27 +02001329{
1330 int rc;
1331
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001332 /* make sure sgsn_vty_init() was called before this */
1333 OSMO_ASSERT(g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +01001334
Harald Welte94508822015-08-15 19:08:21 +02001335 g_cfg->timers.T3312 = GSM0408_T3312_SECS;
1336 g_cfg->timers.T3322 = GSM0408_T3322_SECS;
1337 g_cfg->timers.T3350 = GSM0408_T3350_SECS;
1338 g_cfg->timers.T3360 = GSM0408_T3360_SECS;
1339 g_cfg->timers.T3370 = GSM0408_T3370_SECS;
1340 g_cfg->timers.T3313 = GSM0408_T3313_SECS;
1341 g_cfg->timers.T3314 = GSM0408_T3314_SECS;
1342 g_cfg->timers.T3316 = GSM0408_T3316_SECS;
1343 g_cfg->timers.T3385 = GSM0408_T3385_SECS;
1344 g_cfg->timers.T3386 = GSM0408_T3386_SECS;
1345 g_cfg->timers.T3395 = GSM0408_T3395_SECS;
1346 g_cfg->timers.T3397 = GSM0408_T3397_SECS;
1347
Harald Weltedcccb182010-05-16 20:52:23 +02001348 rc = vty_read_config_file(config_file, NULL);
Harald Welte288be162010-05-01 16:48:27 +02001349 if (rc < 0) {
1350 fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
1351 return rc;
1352 }
1353
Neels Hofmeyr27355c92017-02-24 06:28:31 +01001354 if (g_cfg->auth_policy == SGSN_AUTH_POLICY_REMOTE
1355 && !(g_cfg->gsup_server_addr.sin_addr.s_addr
1356 && g_cfg->gsup_server_port)) {
1357 fprintf(stderr, "Configuration error:"
1358 " 'auth-policy remote' requires both"
1359 " 'gsup remote-ip' and 'gsup remote-port'\n");
1360 return -EINVAL;
1361 }
1362
Harald Welte288be162010-05-01 16:48:27 +02001363 return 0;
1364}