blob: faac69b1dd076bf3dee52875b9941c14b132751a [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);
236 vty_out(vty, " cdr interval %d%s", g_cfg->cdr.interval, VTY_NEWLINE);
237
Harald Welte94508822015-08-15 19:08:21 +0200238 vty_out(vty, " timer t3312 %d%s", g_cfg->timers.T3312, VTY_NEWLINE);
239 vty_out(vty, " timer t3322 %d%s", g_cfg->timers.T3322, VTY_NEWLINE);
240 vty_out(vty, " timer t3350 %d%s", g_cfg->timers.T3350, VTY_NEWLINE);
241 vty_out(vty, " timer t3360 %d%s", g_cfg->timers.T3360, VTY_NEWLINE);
242 vty_out(vty, " timer t3370 %d%s", g_cfg->timers.T3370, VTY_NEWLINE);
243 vty_out(vty, " timer t3313 %d%s", g_cfg->timers.T3313, VTY_NEWLINE);
244 vty_out(vty, " timer t3314 %d%s", g_cfg->timers.T3314, VTY_NEWLINE);
245 vty_out(vty, " timer t3316 %d%s", g_cfg->timers.T3316, VTY_NEWLINE);
246 vty_out(vty, " timer t3385 %d%s", g_cfg->timers.T3385, VTY_NEWLINE);
247 vty_out(vty, " timer t3386 %d%s", g_cfg->timers.T3386, VTY_NEWLINE);
248 vty_out(vty, " timer t3395 %d%s", g_cfg->timers.T3395, VTY_NEWLINE);
249 vty_out(vty, " timer t3397 %d%s", g_cfg->timers.T3397, VTY_NEWLINE);
250
Philippf1f34362016-08-26 17:00:21 +0200251 if (g_cfg->pcomp_rfc1144.active) {
252 vty_out(vty, " compression rfc1144 active slots %d%s",
253 g_cfg->pcomp_rfc1144.s01 + 1, VTY_NEWLINE);
254 } else if (g_cfg->pcomp_rfc1144.passive) {
255 vty_out(vty, " compression rfc1144 passive%s", VTY_NEWLINE);
256 } else
257 vty_out(vty, " no compression rfc1144%s", VTY_NEWLINE);
258
Philipp73f83d52016-09-02 13:38:01 +0200259 if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 1) {
260 vty_out(vty,
261 " compression v42bis active direction sgsn codewords %d strlen %d%s",
262 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
263 VTY_NEWLINE);
264 } else if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 2) {
265 vty_out(vty,
266 " compression v42bis active direction ms codewords %d strlen %d%s",
267 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
268 VTY_NEWLINE);
269 } else if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 3) {
270 vty_out(vty,
271 " compression v42bis active direction both codewords %d strlen %d%s",
272 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
273 VTY_NEWLINE);
274 } else if (g_cfg->dcomp_v42bis.passive) {
275 vty_out(vty, " compression v42bis passive%s", VTY_NEWLINE);
276 } else
277 vty_out(vty, " no compression v42bis%s", VTY_NEWLINE);
278
Neels Hofmeyr2188a772016-05-20 21:59:55 +0200279#ifdef BUILD_IU
Neels Hofmeyra7a39472017-07-05 15:19:52 +0200280 ranap_iu_vty_config_write(vty, " ");
Neels Hofmeyr2188a772016-05-20 21:59:55 +0200281#endif
282
Harald Welte288be162010-05-01 16:48:27 +0200283 return CMD_SUCCESS;
284}
285
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100286#define SGSN_STR "Configure the SGSN\n"
287#define GGSN_STR "Configure the GGSN information\n"
Harald Weltee300d002010-06-02 12:41:34 +0200288
289DEFUN(cfg_sgsn, cfg_sgsn_cmd,
290 "sgsn",
291 SGSN_STR)
Harald Welte288be162010-05-01 16:48:27 +0200292{
293 vty->node = SGSN_NODE;
294 return CMD_SUCCESS;
295}
296
Harald Weltee300d002010-06-02 12:41:34 +0200297DEFUN(cfg_sgsn_bind_addr, cfg_sgsn_bind_addr_cmd,
298 "gtp local-ip A.B.C.D",
299 "GTP Parameters\n"
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100300 "Set the IP address for the local GTP bind\n"
301 "IPv4 Address\n")
Harald Weltee300d002010-06-02 12:41:34 +0200302{
303 inet_aton(argv[0], &g_cfg->gtp_listenaddr.sin_addr);
304
305 return CMD_SUCCESS;
306}
307
Harald Welted193cb32010-05-17 22:58:03 +0200308DEFUN(cfg_ggsn_remote_ip, cfg_ggsn_remote_ip_cmd,
309 "ggsn <0-255> remote-ip A.B.C.D",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100310 GGSN_STR "GGSN Number\n" IP_STR "IPv4 Address\n")
Harald Welted193cb32010-05-17 22:58:03 +0200311{
312 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200313 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welte288be162010-05-01 16:48:27 +0200314
Harald Welted193cb32010-05-17 22:58:03 +0200315 inet_aton(argv[1], &ggc->remote_addr);
Harald Welte288be162010-05-01 16:48:27 +0200316
Harald Welted193cb32010-05-17 22:58:03 +0200317 return CMD_SUCCESS;
318}
319
320#if 0
321DEFUN(cfg_ggsn_remote_port, cfg_ggsn_remote_port_cmd,
322 "ggsn <0-255> remote-port <0-65535>",
323 "")
324{
325 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200326 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welted193cb32010-05-17 22:58:03 +0200327 uint16_t port = atoi(argv[1]);
328
329}
330#endif
331
332DEFUN(cfg_ggsn_gtp_version, cfg_ggsn_gtp_version_cmd,
333 "ggsn <0-255> gtp-version (0|1)",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100334 GGSN_STR "GGSN Number\n" "GTP Version\n"
335 "Version 0\n" "Version 1\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 Welted193cb32010-05-17 22:58:03 +0200339
340 if (atoi(argv[1]))
341 ggc->gtp_version = 1;
342 else
343 ggc->gtp_version = 0;
344
345 return CMD_SUCCESS;
346}
347
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800348DEFUN(cfg_ggsn_dynamic_lookup, cfg_ggsn_dynamic_lookup_cmd,
349 "ggsn dynamic",
350 GGSN_STR "Enable dynamic GRX based look-up (requires restart)\n")
351{
352 sgsn->cfg.dynamic_lookup = 1;
353 return CMD_SUCCESS;
354}
355
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800356DEFUN(cfg_grx_ggsn, cfg_grx_ggsn_cmd,
357 "grx-dns-add A.B.C.D",
358 "Add DNS server\nIPv4 address\n")
359{
360 struct ares_addr_node *node = talloc_zero(tall_bsc_ctx, struct ares_addr_node);
361 node->family = AF_INET;
362 inet_aton(argv[0], &node->addr.addr4);
363
364 node->next = sgsn->ares_servers;
365 sgsn->ares_servers = node;
366 return CMD_SUCCESS;
367}
368
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100369#define APN_STR "Configure the information per APN\n"
370#define APN_GW_STR "The APN gateway name optionally prefixed by '*' (wildcard)\n"
371
372static int add_apn_ggsn_mapping(struct vty *vty, const char *apn_str,
373 const char *imsi_prefix, int ggsn_id)
374{
375 struct apn_ctx *actx;
376 struct sgsn_ggsn_ctx *ggsn;
377
378 ggsn = sgsn_ggsn_ctx_by_id(ggsn_id);
379 if (ggsn == NULL) {
380 vty_out(vty, "%% a GGSN with id %d has not been defined%s",
381 ggsn_id, VTY_NEWLINE);
382 return CMD_WARNING;
383 }
384
385 actx = sgsn_apn_ctx_find_alloc(apn_str, imsi_prefix);
386 if (!actx) {
387 vty_out(vty, "%% unable to create APN context for %s/%s%s",
388 apn_str, imsi_prefix, VTY_NEWLINE);
389 return CMD_WARNING;
390 }
391
392 actx->ggsn = ggsn;
393
394 return CMD_SUCCESS;
395}
396
Harald Welted193cb32010-05-17 22:58:03 +0200397DEFUN(cfg_apn_ggsn, cfg_apn_ggsn_cmd,
398 "apn APNAME ggsn <0-255>",
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100399 APN_STR APN_GW_STR
400 "Select the GGSN to use when the APN gateway prefix matches\n"
401 "The GGSN id")
Harald Welted193cb32010-05-17 22:58:03 +0200402{
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100403
404 return add_apn_ggsn_mapping(vty, argv[0], "", atoi(argv[1]));
Harald Welted193cb32010-05-17 22:58:03 +0200405}
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100406
407DEFUN(cfg_apn_imsi_ggsn, cfg_apn_imsi_ggsn_cmd,
408 "apn APNAME imsi-prefix IMSIPRE ggsn <0-255>",
409 APN_STR APN_GW_STR
410 "Restrict rule to a certain IMSI prefix\n"
411 "An IMSI prefix\n"
412 "Select the GGSN to use when APN gateway and IMSI prefix match\n"
413 "The GGSN id")
414{
415
416 return add_apn_ggsn_mapping(vty, argv[0], argv[1], atoi(argv[2]));
417}
Harald Welted193cb32010-05-17 22:58:03 +0200418
419const struct value_string gprs_mm_st_strs[] = {
420 { GMM_DEREGISTERED, "DEREGISTERED" },
421 { GMM_COMMON_PROC_INIT, "COMMON PROCEDURE (INIT)" },
422 { GMM_REGISTERED_NORMAL, "REGISTERED (NORMAL)" },
Harald Weltebffeff82010-06-09 15:50:45 +0200423 { GMM_REGISTERED_SUSPENDED, "REGISTERED (SUSPENDED)" },
Harald Welted193cb32010-05-17 22:58:03 +0200424 { GMM_DEREGISTERED_INIT, "DEREGISTERED (INIT)" },
425 { 0, NULL }
426};
427
Harald Welte471ac7d2016-12-15 19:48:58 +0100428static char *gtp_ntoa(struct ul16_t *ul)
429{
430 if (ul->l == 4) {
431 struct in_addr *ia = (struct in_addr *) ul;
432 return inet_ntoa(*ia);
433 } else {
434 return "UNKNOWN";
435 }
436}
437
Harald Welted193cb32010-05-17 22:58:03 +0200438static void vty_dump_pdp(struct vty *vty, const char *pfx,
439 struct sgsn_pdp_ctx *pdp)
440{
Jacob Erlbeck99985b52014-10-13 10:32:00 +0200441 const char *imsi = pdp->mm ? pdp->mm->imsi : "(detaching)";
Harald Welte471ac7d2016-12-15 19:48:58 +0100442 vty_out(vty, "%sPDP Context IMSI: %s, SAPI: %u, NSAPI: %u, TI: %u%s",
443 pfx, imsi, pdp->sapi, pdp->nsapi, pdp->ti, VTY_NEWLINE);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200444 if (pdp->lib) {
Max7933d962017-10-19 16:52:30 +0200445 char apnbuf[APN_MAXLEN + 1];
Harald Weltedfbd2c82017-08-13 00:56:45 +0200446 vty_out(vty, "%s APN: %s%s", pfx,
Max7933d962017-10-19 16:52:30 +0200447 osmo_apn_to_str(apnbuf, pdp->lib->apn_use.v, pdp->lib->apn_use.l),
Harald Weltedfbd2c82017-08-13 00:56:45 +0200448 VTY_NEWLINE);
449 vty_out(vty, "%s PDP Address: %s%s", pfx,
450 gprs_pdpaddr2str(pdp->lib->eua.v, pdp->lib->eua.l),
451 VTY_NEWLINE);
452 vty_out(vty, "%s GTP Local Control(%s / TEIC: 0x%08x) ", pfx,
453 gtp_ntoa(&pdp->lib->gsnlc), pdp->lib->teic_own);
454 vty_out(vty, "Data(%s / TEID: 0x%08x)%s",
455 gtp_ntoa(&pdp->lib->gsnlu), pdp->lib->teid_own, VTY_NEWLINE);
456 vty_out(vty, "%s GTP Remote Control(%s / TEIC: 0x%08x) ", pfx,
457 gtp_ntoa(&pdp->lib->gsnrc), pdp->lib->teic_gn);
458 vty_out(vty, "Data(%s / TEID: 0x%08x)%s",
459 gtp_ntoa(&pdp->lib->gsnru), pdp->lib->teid_gn, VTY_NEWLINE);
460 }
Harald Welte471ac7d2016-12-15 19:48:58 +0100461
Harald Welteefbdee92010-06-10 00:20:12 +0200462 vty_out_rate_ctr_group(vty, " ", pdp->ctrg);
Harald Welted193cb32010-05-17 22:58:03 +0200463}
464
465static void vty_dump_mmctx(struct vty *vty, const char *pfx,
466 struct sgsn_mm_ctx *mm, int pdp)
467{
468 vty_out(vty, "%sMM Context for IMSI %s, IMEI %s, P-TMSI %08x%s",
469 pfx, mm->imsi, mm->imei, mm->p_tmsi, VTY_NEWLINE);
Holger Hans Peter Freyther8ee13e22015-05-18 10:00:03 +0200470 vty_out(vty, "%s MSISDN: %s, TLLI: %08x%s HLR: %s",
Harald Weltef97ee042015-12-25 19:12:21 +0100471 pfx, mm->msisdn, mm->gb.tlli, mm->hlr, VTY_NEWLINE);
Harald Welted193cb32010-05-17 22:58:03 +0200472 vty_out(vty, "%s MM State: %s, Routeing Area: %u-%u-%u-%u, "
473 "Cell ID: %u%s", pfx,
Alexander Couzens4f8da6d2017-01-31 15:34:26 +0100474 get_value_string(gprs_mm_st_strs, mm->gmm_state),
Harald Welted193cb32010-05-17 22:58:03 +0200475 mm->ra.mcc, mm->ra.mnc, mm->ra.lac, mm->ra.rac,
Harald Weltef97ee042015-12-25 19:12:21 +0100476 mm->gb.cell_id, VTY_NEWLINE);
Harald Welted193cb32010-05-17 22:58:03 +0200477
Harald Welte8acd88f2010-05-18 10:57:45 +0200478 vty_out_rate_ctr_group(vty, " ", mm->ctrg);
479
Harald Welted193cb32010-05-17 22:58:03 +0200480 if (pdp) {
481 struct sgsn_pdp_ctx *pdp;
482
483 llist_for_each_entry(pdp, &mm->pdp_list, list)
484 vty_dump_pdp(vty, " ", pdp);
485 }
486}
487
488DEFUN(show_sgsn, show_sgsn_cmd, "show sgsn",
489 SHOW_STR "Display information about the SGSN")
490{
Jacob Erlbeck80547992014-12-19 19:19:46 +0100491 if (sgsn->gsup_client) {
492 struct ipa_client_conn *link = sgsn->gsup_client->link;
493 vty_out(vty,
494 " Remote authorization: %sconnected to %s:%d via GSUP%s",
495 sgsn->gsup_client->is_connected ? "" : "not ",
496 link->addr, link->port,
497 VTY_NEWLINE);
498 }
Maxbaabc682017-10-20 13:39:57 +0200499 if (sgsn->gsn)
500 vty_out(vty, " GSN: signalling %s, user traffic %s%s",
501 inet_ntoa(sgsn->gsn->gsnc), inet_ntoa(sgsn->gsn->gsnu), VTY_NEWLINE);
502
Harald Welted193cb32010-05-17 22:58:03 +0200503 /* FIXME: statistics */
504 return CMD_SUCCESS;
505}
506
507#define MMCTX_STR "MM Context\n"
508#define INCLUDE_PDP_STR "Include PDP Context Information\n"
509
510#if 0
511DEFUN(show_mmctx_tlli, show_mmctx_tlli_cmd,
512 "show mm-context tlli HEX [pdp]",
513 SHOW_STR MMCTX_STR "Identify by TLLI\n" "TLLI\n" INCLUDE_PDP_STR)
514{
515 uint32_t tlli;
516 struct sgsn_mm_ctx *mm;
517
518 tlli = strtoul(argv[0], NULL, 16);
519 mm = sgsn_mm_ctx_by_tlli(tlli);
520 if (!mm) {
521 vty_out(vty, "No MM context for TLLI %08x%s",
522 tlli, VTY_NEWLINE);
523 return CMD_WARNING;
524 }
525 vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
526 return CMD_SUCCESS;
527}
528#endif
529
530DEFUN(swow_mmctx_imsi, show_mmctx_imsi_cmd,
531 "show mm-context imsi IMSI [pdp]",
532 SHOW_STR MMCTX_STR "Identify by IMSI\n" "IMSI of the MM Context\n"
533 INCLUDE_PDP_STR)
534{
535 struct sgsn_mm_ctx *mm;
536
537 mm = sgsn_mm_ctx_by_imsi(argv[0]);
538 if (!mm) {
539 vty_out(vty, "No MM context for IMSI %s%s",
540 argv[0], VTY_NEWLINE);
541 return CMD_WARNING;
542 }
543 vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
544 return CMD_SUCCESS;
545}
546
547DEFUN(swow_mmctx_all, show_mmctx_all_cmd,
548 "show mm-context all [pdp]",
549 SHOW_STR MMCTX_STR "All MM Contexts\n" INCLUDE_PDP_STR)
550{
551 struct sgsn_mm_ctx *mm;
552
553 llist_for_each_entry(mm, &sgsn_mm_ctxts, list)
554 vty_dump_mmctx(vty, "", mm, argv[0] ? 1 : 0);
555
556 return CMD_SUCCESS;
557}
558
Harald Welted193cb32010-05-17 22:58:03 +0200559DEFUN(show_pdpctx_all, show_pdpctx_all_cmd,
560 "show pdp-context all",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100561 SHOW_STR "Display information on PDP Context\n" "Show everything\n")
Harald Welted193cb32010-05-17 22:58:03 +0200562{
563 struct sgsn_pdp_ctx *pdp;
564
565 llist_for_each_entry(pdp, &sgsn_pdp_ctxts, g_list)
566 vty_dump_pdp(vty, "", pdp);
567
568 return CMD_SUCCESS;
569}
Harald Welte288be162010-05-01 16:48:27 +0200570
Harald Welte7f6da482013-03-19 11:00:13 +0100571
572DEFUN(imsi_acl, cfg_imsi_acl_cmd,
573 "imsi-acl (add|del) IMSI",
574 "Access Control List of foreign IMSIs\n"
575 "Add IMSI to ACL\n"
576 "Remove IMSI from ACL\n"
577 "IMSI of subscriber\n")
578{
Philipp Maier6ee49d82017-02-28 16:53:07 +0100579 char imsi_sanitized[GSM23003_IMSI_MAX_DIGITS+1];
Harald Welte7f6da482013-03-19 11:00:13 +0100580 const char *op = argv[0];
Philipp Maier6ee49d82017-02-28 16:53:07 +0100581 const char *imsi = imsi_sanitized;
Harald Welte7f6da482013-03-19 11:00:13 +0100582 int rc;
583
Philipp Maier6ee49d82017-02-28 16:53:07 +0100584 /* Sanitize IMSI */
585 if (strlen(argv[1]) > GSM23003_IMSI_MAX_DIGITS) {
586 vty_out(vty, "%% IMSI (%s) too long -- ignored!%s",
587 argv[1], VTY_NEWLINE);
588 return CMD_WARNING;
589 }
590 memset(imsi_sanitized, '0', sizeof(imsi_sanitized));
591 strcpy(imsi_sanitized+GSM23003_IMSI_MAX_DIGITS-strlen(argv[1]),argv[1]);
592
Harald Welte7f6da482013-03-19 11:00:13 +0100593 if (!strcmp(op, "add"))
Jacob Erlbeck3b5d4072014-10-24 15:11:03 +0200594 rc = sgsn_acl_add(imsi, g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +0100595 else
Jacob Erlbeck3b5d4072014-10-24 15:11:03 +0200596 rc = sgsn_acl_del(imsi, g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +0100597
598 if (rc < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100599 vty_out(vty, "%% unable to %s ACL%s", op, VTY_NEWLINE);
Harald Welte7f6da482013-03-19 11:00:13 +0100600 return CMD_WARNING;
601 }
602
603 return CMD_SUCCESS;
604}
605
Max93408ae2016-06-28 14:10:16 +0200606DEFUN(cfg_encrypt, cfg_encrypt_cmd,
607 "encryption (GEA0|GEA1|GEA2|GEA3|GEA4)",
608 "Set encryption algorithm for SGSN\n"
609 "Use GEA0 (no encryption)\n"
610 "Use GEA1\nUse GEA2\nUse GEA3\nUse GEA4\n")
611{
Max93408ae2016-06-28 14:10:16 +0200612 enum gprs_ciph_algo c = get_string_value(gprs_cipher_names, argv[0]);
Max086067f2017-05-02 13:03:28 +0200613 if (c != GPRS_ALGO_GEA0) {
614 if (!gprs_cipher_supported(c)) {
615 vty_out(vty, "%% cipher %s is unsupported in current version%s", argv[0], VTY_NEWLINE);
616 return CMD_WARNING;
617 }
618
619 if (!g_cfg->require_authentication) {
620 vty_out(vty, "%% unable to use encryption %s without authentication: please adjust auth-policy%s",
621 argv[0], VTY_NEWLINE);
622 return CMD_WARNING;
623 }
Max93408ae2016-06-28 14:10:16 +0200624 }
625
626 g_cfg->cipher = c;
627
628 return CMD_SUCCESS;
629}
630
Harald Welte3dfb5492013-03-19 11:48:54 +0100631DEFUN(cfg_auth_policy, cfg_auth_policy_cmd,
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100632 "auth-policy (accept-all|closed|acl-only|remote)",
Harald Welte3dfb5492013-03-19 11:48:54 +0100633 "Autorization Policy of SGSN\n"
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100634 "Accept all IMSIs (DANGEROUS)\n"
635 "Accept only home network subscribers or those in the ACL\n"
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100636 "Accept only subscribers in the ACL\n"
637 "Use remote subscription data only (HLR)\n")
Harald Welte3dfb5492013-03-19 11:48:54 +0100638{
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100639 int val = get_string_value(sgsn_auth_pol_strs, argv[0]);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100640 OSMO_ASSERT(val >= SGSN_AUTH_POLICY_OPEN && val <= SGSN_AUTH_POLICY_REMOTE);
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100641 g_cfg->auth_policy = val;
Jacob Erlbeck9d4f46c2014-12-17 13:20:08 +0100642 g_cfg->require_authentication = (val == SGSN_AUTH_POLICY_REMOTE);
Jacob Erlbeck771573c2014-12-19 18:08:48 +0100643 g_cfg->require_update_location = (val == SGSN_AUTH_POLICY_REMOTE);
Harald Welte3dfb5492013-03-19 11:48:54 +0100644
645 return CMD_SUCCESS;
646}
647
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100648/* Subscriber */
Neels Hofmeyr396f2e62017-09-04 15:13:25 +0200649#include <osmocom/sgsn/gprs_subscriber.h>
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100650
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100651static void subscr_dump_full_vty(struct vty *vty, struct gprs_subscr *gsub, int pending)
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100652{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100653#if 0
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100654 char expire_time[200];
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100655#endif
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100656 struct gsm_auth_tuple *at;
657 int at_idx;
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100658 struct sgsn_subscriber_pdp_data *pdp;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100659
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100660 vty_out(vty, " Authorized: %d%s",
661 gsub->authorized, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100662 vty_out(vty, " LAC: %d/0x%x%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100663 gsub->lac, gsub->lac, VTY_NEWLINE);
664 vty_out(vty, " IMSI: %s%s", gsub->imsi, VTY_NEWLINE);
665 if (gsub->tmsi != GSM_RESERVED_TMSI)
666 vty_out(vty, " TMSI: %08X%s", gsub->tmsi,
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100667 VTY_NEWLINE);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100668 if (gsub->sgsn_data->msisdn_len > 0)
Holger Hans Peter Freytherf7b38262015-04-23 16:58:33 -0400669 vty_out(vty, " MSISDN (BCD): %s%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100670 osmo_hexdump(gsub->sgsn_data->msisdn,
671 gsub->sgsn_data->msisdn_len),
Holger Hans Peter Freytherf7b38262015-04-23 16:58:33 -0400672 VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100673
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100674 if (strlen(gsub->imei) > 0)
675 vty_out(vty, " IMEI: %s%s", gsub->imei, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100676
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100677 for (at_idx = 0; at_idx < ARRAY_SIZE(gsub->sgsn_data->auth_triplets);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100678 at_idx++) {
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100679 at = &gsub->sgsn_data->auth_triplets[at_idx];
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100680 if (at->key_seq == GSM_KEY_SEQ_INVAL)
681 continue;
682
683 vty_out(vty, " A3A8 tuple (used %d times): ",
684 at->use_count);
Harald Welte89837d42016-05-06 23:28:11 +0200685 vty_out(vty, " CKSN: %d, ",
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100686 at->key_seq);
Harald Welte89837d42016-05-06 23:28:11 +0200687 if (at->vec.auth_types & OSMO_AUTH_TYPE_GSM) {
688 vty_out(vty, "RAND: %s, ",
689 osmo_hexdump(at->vec.rand,
690 sizeof(at->vec.rand)));
691 vty_out(vty, "SRES: %s, ",
692 osmo_hexdump(at->vec.sres,
693 sizeof(at->vec.sres)));
694 vty_out(vty, "Kc: %s%s",
695 osmo_hexdump(at->vec.kc,
696 sizeof(at->vec.kc)), VTY_NEWLINE);
697 }
698 if (at->vec.auth_types & OSMO_AUTH_TYPE_UMTS) {
699 vty_out(vty, " AUTN: %s, ",
700 osmo_hexdump(at->vec.autn,
701 sizeof(at->vec.autn)));
702 vty_out(vty, "RES: %s, ",
703 osmo_hexdump(at->vec.res, at->vec.res_len));
704 vty_out(vty, "IK: %s, ",
705 osmo_hexdump(at->vec.ik, sizeof(at->vec.ik)));
706 vty_out(vty, "CK: %s, ",
707 osmo_hexdump(at->vec.ck, sizeof(at->vec.ck)));
708 }
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100709 }
710
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100711 llist_for_each_entry(pdp, &gsub->sgsn_data->pdp_list, list) {
Holger Hans Peter Freytherd05e0692015-04-23 16:59:04 -0400712 vty_out(vty, " PDP info: Id: %d, Type: 0x%04x, APN: '%s' QoS: %s%s",
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100713 pdp->context_id, pdp->pdp_type, pdp->apn_str,
Holger Hans Peter Freytherd05e0692015-04-23 16:59:04 -0400714 osmo_hexdump(pdp->qos_subscribed, pdp->qos_subscribed_len),
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100715 VTY_NEWLINE);
716 }
717
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100718#if 0
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100719 /* print the expiration time of a subscriber */
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100720 if (gsub->expire_lu) {
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100721 strftime(expire_time, sizeof(expire_time),
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100722 "%a, %d %b %Y %T %z", localtime(&gsub->expire_lu));
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100723 expire_time[sizeof(expire_time) - 1] = '\0';
724 vty_out(vty, " Expiration Time: %s%s", expire_time, VTY_NEWLINE);
725 }
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100726#endif
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100727
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100728 if (gsub->flags)
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100729 vty_out(vty, " Flags: %s%s%s%s%s%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100730 gsub->flags & GPRS_SUBSCRIBER_FIRST_CONTACT ?
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100731 "FIRST_CONTACT " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100732 gsub->flags & GPRS_SUBSCRIBER_CANCELLED ?
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100733 "CANCELLED " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100734 gsub->flags & GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING ?
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100735 "UPDATE_LOCATION_PENDING " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100736 gsub->flags & GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING ?
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100737 "AUTH_INFO_PENDING " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100738 gsub->flags & GPRS_SUBSCRIBER_ENABLE_PURGE ?
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100739 "ENABLE_PURGE " : "",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100740 VTY_NEWLINE);
741
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100742 vty_out(vty, " Use count: %u%s", gsub->use_count, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100743}
744
745DEFUN(show_subscr_cache,
746 show_subscr_cache_cmd,
747 "show subscriber cache",
748 SHOW_STR "Show information about subscribers\n"
749 "Display contents of subscriber cache\n")
750{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100751 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100752
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100753 llist_for_each_entry(subscr, gprs_subscribers, entry) {
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100754 vty_out(vty, " Subscriber:%s", VTY_NEWLINE);
755 subscr_dump_full_vty(vty, subscr, 0);
756 }
757
758 return CMD_SUCCESS;
759}
760
761#define UPDATE_SUBSCR_STR "update-subscriber imsi IMSI "
762#define UPDATE_SUBSCR_HELP "Update subscriber list\n" \
763 "Use the IMSI to select the subscriber\n" \
764 "The IMSI\n"
765
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100766#define UPDATE_SUBSCR_INSERT_HELP "Insert data into the subscriber record\n"
767
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100768DEFUN(update_subscr_insert_auth_triplet, update_subscr_insert_auth_triplet_cmd,
769 UPDATE_SUBSCR_STR "insert auth-triplet <1-5> sres SRES rand RAND kc KC",
770 UPDATE_SUBSCR_HELP
771 UPDATE_SUBSCR_INSERT_HELP
772 "Update authentication triplet\n"
773 "Triplet index\n"
774 "Set SRES value\nSRES value (4 byte) in hex\n"
775 "Set RAND value\nRAND value (16 byte) in hex\n"
776 "Set Kc value\nKc value (8 byte) in hex\n")
777{
778 const char *imsi = argv[0];
779 const int cksn = atoi(argv[1]) - 1;
780 const char *sres_str = argv[2];
781 const char *rand_str = argv[3];
782 const char *kc_str = argv[4];
783 struct gsm_auth_tuple at = {0,};
784
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100785 struct gprs_subscr *subscr;
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100786
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100787 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100788 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100789 vty_out(vty, "%% unable get subscriber record for %s%s",
790 imsi, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100791 return CMD_WARNING;
792 }
793
794 OSMO_ASSERT(subscr->sgsn_data);
795
Harald Welte121e9a42016-04-20 13:13:19 +0200796 if (osmo_hexparse(sres_str, &at.vec.sres[0], sizeof(at.vec.sres)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100797 vty_out(vty, "%% invalid SRES value '%s'%s",
798 sres_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100799 goto failed;
800 }
Harald Welte121e9a42016-04-20 13:13:19 +0200801 if (osmo_hexparse(rand_str, &at.vec.rand[0], sizeof(at.vec.rand)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100802 vty_out(vty, "%% invalid RAND value '%s'%s",
803 rand_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100804 goto failed;
805 }
Harald Welte121e9a42016-04-20 13:13:19 +0200806 if (osmo_hexparse(kc_str, &at.vec.kc[0], sizeof(at.vec.kc)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100807 vty_out(vty, "%% invalid Kc value '%s'%s",
808 kc_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100809 goto failed;
810 }
811 at.key_seq = cksn;
812
813 subscr->sgsn_data->auth_triplets[cksn] = at;
814 subscr->sgsn_data->auth_triplets_updated = 1;
815
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100816 gprs_subscr_put(subscr);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100817
818 return CMD_SUCCESS;
819
820failed:
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100821 gprs_subscr_put(subscr);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100822 return CMD_SUCCESS;
823}
824
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100825DEFUN(update_subscr_cancel, update_subscr_cancel_cmd,
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100826 UPDATE_SUBSCR_STR "cancel (update-procedure|subscription-withdraw)",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100827 UPDATE_SUBSCR_HELP
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100828 "Cancel (remove) subscriber record\n"
829 "The MS moved to another SGSN\n"
830 "The subscription is no longer valid\n")
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100831{
832 const char *imsi = argv[0];
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100833 const char *cancel_type = argv[1];
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100834
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100835 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100836
837 subscr = gprs_subscr_get_by_imsi(imsi);
838 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100839 vty_out(vty, "%% no subscriber record for %s%s",
840 imsi, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100841 return CMD_WARNING;
842 }
843
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100844 if (strcmp(cancel_type, "update-procedure") == 0)
845 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
846 else
847 subscr->sgsn_data->error_cause = GMM_CAUSE_IMPL_DETACHED;
848
Jacob Erlbeck37139e52015-01-23 13:52:55 +0100849 gprs_subscr_cancel(subscr);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100850 gprs_subscr_put(subscr);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100851
852 return CMD_SUCCESS;
853}
854
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100855DEFUN(update_subscr_create, update_subscr_create_cmd,
856 UPDATE_SUBSCR_STR "create",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100857 UPDATE_SUBSCR_HELP
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100858 "Create a subscriber entry\n")
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100859{
860 const char *imsi = argv[0];
861
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100862 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100863
864 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100865 if (subscr) {
866 vty_out(vty, "%% subscriber record already exists for %s%s",
867 imsi, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100868 return CMD_WARNING;
869 }
870
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100871 subscr = gprs_subscr_get_or_create(imsi);
872 subscr->keep_in_ram = 1;
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100873 gprs_subscr_put(subscr);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100874
875 return CMD_SUCCESS;
876}
877
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100878DEFUN(update_subscr_destroy, update_subscr_destroy_cmd,
879 UPDATE_SUBSCR_STR "destroy",
880 UPDATE_SUBSCR_HELP
881 "Destroy a subscriber entry\n")
882{
883 const char *imsi = argv[0];
884
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100885 struct gprs_subscr *subscr;
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100886
887 subscr = gprs_subscr_get_by_imsi(imsi);
888 if (!subscr) {
889 vty_out(vty, "%% subscriber record does not exist for %s%s",
890 imsi, VTY_NEWLINE);
891 return CMD_WARNING;
892 }
893
894 subscr->keep_in_ram = 0;
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100895 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100896 gprs_subscr_cancel(subscr);
897 if (subscr->use_count > 1)
898 vty_out(vty, "%% subscriber is still in use%s",
899 VTY_NEWLINE);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100900 gprs_subscr_put(subscr);
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100901
902 return CMD_SUCCESS;
903}
904
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100905#define UL_ERR_STR "system-failure|data-missing|unexpected-data-value|" \
906 "unknown-subscriber|roaming-not-allowed"
907
908#define UL_ERR_HELP \
909 "Force error code SystemFailure\n" \
910 "Force error code DataMissing\n" \
911 "Force error code UnexpectedDataValue\n" \
912 "Force error code UnknownSubscriber\n" \
913 "Force error code RoamingNotAllowed\n"
914
915DEFUN(update_subscr_update_location_result, update_subscr_update_location_result_cmd,
916 UPDATE_SUBSCR_STR "update-location-result (ok|" UL_ERR_STR ")",
917 UPDATE_SUBSCR_HELP
918 "Complete the update location procedure\n"
919 "The update location request succeeded\n"
920 UL_ERR_HELP)
921{
922 const char *imsi = argv[0];
923 const char *ret_code_str = argv[1];
924
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100925 struct gprs_subscr *subscr;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100926
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100927 const struct value_string cause_mapping[] = {
928 { GMM_CAUSE_NET_FAIL, "system-failure" },
929 { GMM_CAUSE_INV_MAND_INFO, "data-missing" },
930 { GMM_CAUSE_PROTO_ERR_UNSPEC, "unexpected-data-value" },
931 { GMM_CAUSE_IMSI_UNKNOWN, "unknown-subscriber" },
932 { GMM_CAUSE_GPRS_NOTALLOWED, "roaming-not-allowed" },
933 { 0, NULL }
934 };
935
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100936 subscr = gprs_subscr_get_by_imsi(imsi);
937 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100938 vty_out(vty, "%% unable to get subscriber record for %s%s",
939 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100940 return CMD_WARNING;
941 }
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100942
943 if (strcmp(ret_code_str, "ok") == 0) {
944 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100945 subscr->authorized = 1;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100946 } else {
947 subscr->sgsn_data->error_cause =
948 get_string_value(cause_mapping, ret_code_str);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100949 subscr->authorized = 0;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100950 }
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100951
952 gprs_subscr_update(subscr);
953
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100954 gprs_subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100955
956 return CMD_SUCCESS;
957}
958
959DEFUN(update_subscr_update_auth_info, update_subscr_update_auth_info_cmd,
960 UPDATE_SUBSCR_STR "update-auth-info",
961 UPDATE_SUBSCR_HELP
962 "Complete the send authentication info procedure\n")
963{
964 const char *imsi = argv[0];
965
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100966 struct gprs_subscr *subscr;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100967
968 subscr = gprs_subscr_get_by_imsi(imsi);
969 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100970 vty_out(vty, "%% unable to get subscriber record for %s%s",
971 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100972 return CMD_WARNING;
973 }
974
975 gprs_subscr_update_auth_info(subscr);
976
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100977 gprs_subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100978
979 return CMD_SUCCESS;
980}
981
Jacob Erlbeck39f040d2014-12-18 12:46:47 +0100982DEFUN(cfg_gsup_remote_ip, cfg_gsup_remote_ip_cmd,
983 "gsup remote-ip A.B.C.D",
984 "GSUP Parameters\n"
985 "Set the IP address of the remote GSUP server\n"
986 "IPv4 Address\n")
987{
988 inet_aton(argv[0], &g_cfg->gsup_server_addr.sin_addr);
989
990 return CMD_SUCCESS;
991}
992
993DEFUN(cfg_gsup_remote_port, cfg_gsup_remote_port_cmd,
994 "gsup remote-port <0-65535>",
995 "GSUP Parameters\n"
996 "Set the TCP port of the remote GSUP server\n"
997 "Remote TCP port\n")
998{
999 g_cfg->gsup_server_port = atoi(argv[0]);
1000
1001 return CMD_SUCCESS;
1002}
1003
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001004DEFUN(cfg_gsup_oap_id, cfg_gsup_oap_id_cmd,
1005 "gsup oap-id <0-65535>",
1006 "GSUP Parameters\n"
1007 "Set the SGSN's OAP client ID\nOAP client ID (0 == disabled)\n")
1008{
1009 /* VTY ensures range */
1010 g_cfg->oap.client_id = (uint16_t)atoi(argv[0]);
1011 return CMD_SUCCESS;
1012}
1013
1014DEFUN(cfg_gsup_oap_k, cfg_gsup_oap_k_cmd,
1015 "gsup oap-k K",
1016 "GSUP Parameters\n"
1017 "Set the OAP shared secret K\nK value (16 byte) hex\n")
1018{
1019 const char *k = argv[0];
1020
1021 g_cfg->oap.secret_k_present = 0;
1022
1023 if ((!k) || (strlen(k) == 0))
1024 goto disable;
1025
1026 int k_len = osmo_hexparse(k,
1027 g_cfg->oap.secret_k,
1028 sizeof(g_cfg->oap.secret_k));
1029 if (k_len != 16) {
1030 vty_out(vty, "%% need exactly 16 octets for oap-k, got %d.%s",
1031 k_len, VTY_NEWLINE);
1032 goto disable;
1033 }
1034
1035 g_cfg->oap.secret_k_present = 1;
1036 return CMD_SUCCESS;
1037
1038disable:
1039 if (g_cfg->oap.client_id > 0) {
1040 vty_out(vty, "%% OAP client ID set, but invalid oap-k value disables OAP.%s",
1041 VTY_NEWLINE);
1042 return CMD_WARNING;
1043 }
1044 return CMD_SUCCESS;
1045}
1046
1047DEFUN(cfg_gsup_oap_opc, cfg_gsup_oap_opc_cmd,
1048 "gsup oap-opc OPC",
1049 "GSUP Parameters\n"
1050 "Set the OAP shared secret OPC\nOPC value (16 byte) hex\n")
1051{
1052 const char *opc = argv[0];
1053
1054 g_cfg->oap.secret_opc_present = 0;
1055
1056 if ((!opc) || (strlen(opc) == 0))
1057 goto disable;
1058
1059 int opc_len = osmo_hexparse(opc,
1060 g_cfg->oap.secret_opc,
1061 sizeof(g_cfg->oap.secret_opc));
1062 if (opc_len != 16) {
1063 vty_out(vty, "%% need exactly 16 octets for oap-opc, got %d.%s",
1064 opc_len, VTY_NEWLINE);
1065 goto disable;
1066 }
1067
1068 g_cfg->oap.secret_opc_present = 1;
1069 return CMD_SUCCESS;
1070
1071disable:
1072 if (g_cfg->oap.client_id > 0) {
1073 vty_out(vty, "%% OAP client ID set, but invalid oap-opc value disables OAP.%s",
1074 VTY_NEWLINE);
1075 return CMD_WARNING;
1076 }
1077 return CMD_SUCCESS;
1078}
1079
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001080DEFUN(cfg_apn_name, cfg_apn_name_cmd,
1081 "access-point-name NAME",
1082 "Configure a global list of allowed APNs\n"
1083 "Add this NAME to the list\n")
1084{
1085 return add_apn_ggsn_mapping(vty, argv[0], "", 0);
1086}
1087
1088DEFUN(cfg_no_apn_name, cfg_no_apn_name_cmd,
1089 "no access-point-name NAME",
1090 NO_STR "Configure a global list of allowed APNs\n"
1091 "Remove entry with NAME\n")
1092{
1093 struct apn_ctx *apn_ctx = sgsn_apn_ctx_by_name(argv[0], "");
1094 if (!apn_ctx)
1095 return CMD_SUCCESS;
1096
1097 sgsn_apn_ctx_free(apn_ctx);
1098 return CMD_SUCCESS;
1099}
1100
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001101DEFUN(cfg_cdr_filename, cfg_cdr_filename_cmd,
1102 "cdr filename NAME",
1103 "CDR\nSet filename\nname\n")
1104{
1105 talloc_free(g_cfg->cdr.filename);
1106 g_cfg->cdr.filename = talloc_strdup(tall_vty_ctx, argv[0]);
1107 return CMD_SUCCESS;
1108}
1109
1110DEFUN(cfg_no_cdr_filename, cfg_no_cdr_filename_cmd,
1111 "no cdr filename",
1112 NO_STR "CDR\nDisable CDR generation\n")
1113{
1114 talloc_free(g_cfg->cdr.filename);
1115 g_cfg->cdr.filename = NULL;
1116 return CMD_SUCCESS;
1117}
1118
1119DEFUN(cfg_cdr_interval, cfg_cdr_interval_cmd,
1120 "cdr interval <1-2147483647>",
1121 "CDR\nPDP periodic log interval\nSeconds\n")
1122{
1123 g_cfg->cdr.interval = atoi(argv[0]);
1124 return CMD_SUCCESS;
1125}
1126
Philippf1f34362016-08-26 17:00:21 +02001127#define COMPRESSION_STR "Configure compression\n"
1128DEFUN(cfg_no_comp_rfc1144, cfg_no_comp_rfc1144_cmd,
1129 "no compression rfc1144",
1130 NO_STR COMPRESSION_STR "disable rfc1144 TCP/IP header compression\n")
1131{
1132 g_cfg->pcomp_rfc1144.active = 0;
1133 g_cfg->pcomp_rfc1144.passive = 0;
1134 return CMD_SUCCESS;
1135}
1136
1137DEFUN(cfg_comp_rfc1144, cfg_comp_rfc1144_cmd,
1138 "compression rfc1144 active slots <1-256>",
1139 COMPRESSION_STR
1140 "RFC1144 Header compresion scheme\n"
1141 "Compression is actively proposed\n"
1142 "Number of compression state slots\n"
1143 "Number of compression state slots\n")
1144{
1145 g_cfg->pcomp_rfc1144.active = 1;
1146 g_cfg->pcomp_rfc1144.passive = 1;
1147 g_cfg->pcomp_rfc1144.s01 = atoi(argv[0]) - 1;
1148 return CMD_SUCCESS;
1149}
1150
1151DEFUN(cfg_comp_rfc1144p, cfg_comp_rfc1144p_cmd,
1152 "compression rfc1144 passive",
1153 COMPRESSION_STR
1154 "RFC1144 Header compresion scheme\n"
1155 "Compression is available on request\n")
1156{
1157 g_cfg->pcomp_rfc1144.active = 0;
1158 g_cfg->pcomp_rfc1144.passive = 1;
1159 return CMD_SUCCESS;
1160}
1161
Philipp73f83d52016-09-02 13:38:01 +02001162DEFUN(cfg_no_comp_v42bis, cfg_no_comp_v42bis_cmd,
1163 "no compression v42bis",
1164 NO_STR COMPRESSION_STR "disable V.42bis data compression\n")
1165{
1166 g_cfg->dcomp_v42bis.active = 0;
1167 g_cfg->dcomp_v42bis.passive = 0;
1168 return CMD_SUCCESS;
1169}
1170
1171DEFUN(cfg_comp_v42bis, cfg_comp_v42bis_cmd,
1172 "compression v42bis active direction (ms|sgsn|both) codewords <512-65535> strlen <6-250>",
1173 COMPRESSION_STR
1174 "V.42bis data compresion scheme\n"
1175 "Compression is actively proposed\n"
1176 "Direction in which the compression shall be active (p0)\n"
1177 "Compress ms->sgsn direction only\n"
1178 "Compress sgsn->ms direction only\n"
1179 "Both directions\n"
1180 "Number of codewords (p1)\n"
1181 "Number of codewords\n"
1182 "Maximum string length (p2)\n" "Maximum string length\n")
1183{
1184 g_cfg->dcomp_v42bis.active = 1;
1185 g_cfg->dcomp_v42bis.passive = 1;
1186
1187 switch (argv[0][0]) {
1188 case 'm':
1189 g_cfg->dcomp_v42bis.p0 = 1;
1190 break;
1191 case 's':
1192 g_cfg->dcomp_v42bis.p0 = 2;
1193 break;
1194 case 'b':
1195 g_cfg->dcomp_v42bis.p0 = 3;
1196 break;
1197 }
1198
1199 g_cfg->dcomp_v42bis.p1 = atoi(argv[1]);
1200 g_cfg->dcomp_v42bis.p2 = atoi(argv[2]);
1201 return CMD_SUCCESS;
1202}
1203
1204DEFUN(cfg_comp_v42bisp, cfg_comp_v42bisp_cmd,
1205 "compression v42bis passive",
1206 COMPRESSION_STR
1207 "V.42bis data compresion scheme\n"
1208 "Compression is available on request\n")
1209{
1210 g_cfg->dcomp_v42bis.active = 0;
1211 g_cfg->dcomp_v42bis.passive = 1;
1212 return CMD_SUCCESS;
1213}
1214
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001215int sgsn_vty_init(struct sgsn_config *cfg)
Harald Welte288be162010-05-01 16:48:27 +02001216{
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001217 g_cfg = cfg;
1218
Harald Welted193cb32010-05-17 22:58:03 +02001219 install_element_ve(&show_sgsn_cmd);
1220 //install_element_ve(&show_mmctx_tlli_cmd);
1221 install_element_ve(&show_mmctx_imsi_cmd);
1222 install_element_ve(&show_mmctx_all_cmd);
1223 install_element_ve(&show_pdpctx_all_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001224 install_element_ve(&show_subscr_cache_cmd);
1225
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01001226 install_element(ENABLE_NODE, &update_subscr_insert_auth_triplet_cmd);
Jacob Erlbeckd9193432015-01-19 14:11:46 +01001227 install_element(ENABLE_NODE, &update_subscr_create_cmd);
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001228 install_element(ENABLE_NODE, &update_subscr_destroy_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001229 install_element(ENABLE_NODE, &update_subscr_cancel_cmd);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001230 install_element(ENABLE_NODE, &update_subscr_update_location_result_cmd);
1231 install_element(ENABLE_NODE, &update_subscr_update_auth_info_cmd);
Harald Welte288be162010-05-01 16:48:27 +02001232
1233 install_element(CONFIG_NODE, &cfg_sgsn_cmd);
1234 install_node(&sgsn_node, config_write_sgsn);
Jacob Erlbeck36722e12013-10-29 09:30:30 +01001235 vty_install_default(SGSN_NODE);
Harald Weltee300d002010-06-02 12:41:34 +02001236 install_element(SGSN_NODE, &cfg_sgsn_bind_addr_cmd);
Harald Welted193cb32010-05-17 22:58:03 +02001237 install_element(SGSN_NODE, &cfg_ggsn_remote_ip_cmd);
1238 //install_element(SGSN_NODE, &cfg_ggsn_remote_port_cmd);
1239 install_element(SGSN_NODE, &cfg_ggsn_gtp_version_cmd);
Harald Welte7f6da482013-03-19 11:00:13 +01001240 install_element(SGSN_NODE, &cfg_imsi_acl_cmd);
Harald Welte3dfb5492013-03-19 11:48:54 +01001241 install_element(SGSN_NODE, &cfg_auth_policy_cmd);
Max93408ae2016-06-28 14:10:16 +02001242 install_element(SGSN_NODE, &cfg_encrypt_cmd);
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001243 install_element(SGSN_NODE, &cfg_gsup_remote_ip_cmd);
1244 install_element(SGSN_NODE, &cfg_gsup_remote_port_cmd);
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001245 install_element(SGSN_NODE, &cfg_gsup_oap_id_cmd);
1246 install_element(SGSN_NODE, &cfg_gsup_oap_k_cmd);
1247 install_element(SGSN_NODE, &cfg_gsup_oap_opc_cmd);
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +01001248 install_element(SGSN_NODE, &cfg_apn_ggsn_cmd);
1249 install_element(SGSN_NODE, &cfg_apn_imsi_ggsn_cmd);
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001250 install_element(SGSN_NODE, &cfg_apn_name_cmd);
1251 install_element(SGSN_NODE, &cfg_no_apn_name_cmd);
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001252 install_element(SGSN_NODE, &cfg_cdr_filename_cmd);
1253 install_element(SGSN_NODE, &cfg_no_cdr_filename_cmd);
1254 install_element(SGSN_NODE, &cfg_cdr_interval_cmd);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001255 install_element(SGSN_NODE, &cfg_ggsn_dynamic_lookup_cmd);
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +08001256 install_element(SGSN_NODE, &cfg_grx_ggsn_cmd);
Harald Welte288be162010-05-01 16:48:27 +02001257
Harald Welte94508822015-08-15 19:08:21 +02001258 install_element(SGSN_NODE, &cfg_sgsn_T3312_cmd);
1259 install_element(SGSN_NODE, &cfg_sgsn_T3322_cmd);
1260 install_element(SGSN_NODE, &cfg_sgsn_T3350_cmd);
1261 install_element(SGSN_NODE, &cfg_sgsn_T3360_cmd);
1262 install_element(SGSN_NODE, &cfg_sgsn_T3370_cmd);
1263 install_element(SGSN_NODE, &cfg_sgsn_T3313_cmd);
1264 install_element(SGSN_NODE, &cfg_sgsn_T3314_cmd);
1265 install_element(SGSN_NODE, &cfg_sgsn_T3316_cmd);
1266 install_element(SGSN_NODE, &cfg_sgsn_T3385_cmd);
1267 install_element(SGSN_NODE, &cfg_sgsn_T3386_cmd);
1268 install_element(SGSN_NODE, &cfg_sgsn_T3395_cmd);
1269 install_element(SGSN_NODE, &cfg_sgsn_T3397_cmd);
1270
Philippf1f34362016-08-26 17:00:21 +02001271 install_element(SGSN_NODE, &cfg_no_comp_rfc1144_cmd);
1272 install_element(SGSN_NODE, &cfg_comp_rfc1144_cmd);
1273 install_element(SGSN_NODE, &cfg_comp_rfc1144p_cmd);
Philipp73f83d52016-09-02 13:38:01 +02001274 install_element(SGSN_NODE, &cfg_no_comp_v42bis_cmd);
1275 install_element(SGSN_NODE, &cfg_comp_v42bis_cmd);
1276 install_element(SGSN_NODE, &cfg_comp_v42bisp_cmd);
Neels Hofmeyr2188a772016-05-20 21:59:55 +02001277
1278#ifdef BUILD_IU
Neels Hofmeyra7a39472017-07-05 15:19:52 +02001279 ranap_iu_vty_init(SGSN_NODE, &g_cfg->iu.rab_assign_addr_enc);
Neels Hofmeyr2188a772016-05-20 21:59:55 +02001280#endif
Harald Welte288be162010-05-01 16:48:27 +02001281 return 0;
1282}
1283
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001284int sgsn_parse_config(const char *config_file)
Harald Welte288be162010-05-01 16:48:27 +02001285{
1286 int rc;
1287
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001288 /* make sure sgsn_vty_init() was called before this */
1289 OSMO_ASSERT(g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +01001290
Harald Welte94508822015-08-15 19:08:21 +02001291 g_cfg->timers.T3312 = GSM0408_T3312_SECS;
1292 g_cfg->timers.T3322 = GSM0408_T3322_SECS;
1293 g_cfg->timers.T3350 = GSM0408_T3350_SECS;
1294 g_cfg->timers.T3360 = GSM0408_T3360_SECS;
1295 g_cfg->timers.T3370 = GSM0408_T3370_SECS;
1296 g_cfg->timers.T3313 = GSM0408_T3313_SECS;
1297 g_cfg->timers.T3314 = GSM0408_T3314_SECS;
1298 g_cfg->timers.T3316 = GSM0408_T3316_SECS;
1299 g_cfg->timers.T3385 = GSM0408_T3385_SECS;
1300 g_cfg->timers.T3386 = GSM0408_T3386_SECS;
1301 g_cfg->timers.T3395 = GSM0408_T3395_SECS;
1302 g_cfg->timers.T3397 = GSM0408_T3397_SECS;
1303
Harald Weltedcccb182010-05-16 20:52:23 +02001304 rc = vty_read_config_file(config_file, NULL);
Harald Welte288be162010-05-01 16:48:27 +02001305 if (rc < 0) {
1306 fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
1307 return rc;
1308 }
1309
Neels Hofmeyr27355c92017-02-24 06:28:31 +01001310 if (g_cfg->auth_policy == SGSN_AUTH_POLICY_REMOTE
1311 && !(g_cfg->gsup_server_addr.sin_addr.s_addr
1312 && g_cfg->gsup_server_port)) {
1313 fprintf(stderr, "Configuration error:"
1314 " 'auth-policy remote' requires both"
1315 " 'gsup remote-ip' and 'gsup remote-port'\n");
1316 return -EINVAL;
1317 }
1318
Harald Welte288be162010-05-01 16:48:27 +02001319 return 0;
1320}