blob: e9ce1998c980503927d8b53a391cb8bd99ec1a0f [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"
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100304 "Set the IP address for the local GTP bind\n"
305 "IPv4 Address\n")
Harald Weltee300d002010-06-02 12:41:34 +0200306{
307 inet_aton(argv[0], &g_cfg->gtp_listenaddr.sin_addr);
308
309 return CMD_SUCCESS;
310}
311
Harald Welted193cb32010-05-17 22:58:03 +0200312DEFUN(cfg_ggsn_remote_ip, cfg_ggsn_remote_ip_cmd,
313 "ggsn <0-255> remote-ip A.B.C.D",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100314 GGSN_STR "GGSN Number\n" IP_STR "IPv4 Address\n")
Harald Welted193cb32010-05-17 22:58:03 +0200315{
316 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200317 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welte288be162010-05-01 16:48:27 +0200318
Harald Welted193cb32010-05-17 22:58:03 +0200319 inet_aton(argv[1], &ggc->remote_addr);
Harald Welte288be162010-05-01 16:48:27 +0200320
Harald Welted193cb32010-05-17 22:58:03 +0200321 return CMD_SUCCESS;
322}
323
324#if 0
325DEFUN(cfg_ggsn_remote_port, cfg_ggsn_remote_port_cmd,
326 "ggsn <0-255> remote-port <0-65535>",
327 "")
328{
329 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200330 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welted193cb32010-05-17 22:58:03 +0200331 uint16_t port = atoi(argv[1]);
332
333}
334#endif
335
336DEFUN(cfg_ggsn_gtp_version, cfg_ggsn_gtp_version_cmd,
337 "ggsn <0-255> gtp-version (0|1)",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100338 GGSN_STR "GGSN Number\n" "GTP Version\n"
339 "Version 0\n" "Version 1\n")
Harald Welted193cb32010-05-17 22:58:03 +0200340{
341 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200342 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welted193cb32010-05-17 22:58:03 +0200343
344 if (atoi(argv[1]))
345 ggc->gtp_version = 1;
346 else
347 ggc->gtp_version = 0;
348
349 return CMD_SUCCESS;
350}
351
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800352DEFUN(cfg_ggsn_dynamic_lookup, cfg_ggsn_dynamic_lookup_cmd,
353 "ggsn dynamic",
354 GGSN_STR "Enable dynamic GRX based look-up (requires restart)\n")
355{
356 sgsn->cfg.dynamic_lookup = 1;
357 return CMD_SUCCESS;
358}
359
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800360DEFUN(cfg_grx_ggsn, cfg_grx_ggsn_cmd,
361 "grx-dns-add A.B.C.D",
362 "Add DNS server\nIPv4 address\n")
363{
364 struct ares_addr_node *node = talloc_zero(tall_bsc_ctx, struct ares_addr_node);
365 node->family = AF_INET;
366 inet_aton(argv[0], &node->addr.addr4);
367
368 node->next = sgsn->ares_servers;
369 sgsn->ares_servers = node;
370 return CMD_SUCCESS;
371}
372
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100373#define APN_STR "Configure the information per APN\n"
374#define APN_GW_STR "The APN gateway name optionally prefixed by '*' (wildcard)\n"
375
376static int add_apn_ggsn_mapping(struct vty *vty, const char *apn_str,
377 const char *imsi_prefix, int ggsn_id)
378{
379 struct apn_ctx *actx;
380 struct sgsn_ggsn_ctx *ggsn;
381
382 ggsn = sgsn_ggsn_ctx_by_id(ggsn_id);
383 if (ggsn == NULL) {
384 vty_out(vty, "%% a GGSN with id %d has not been defined%s",
385 ggsn_id, VTY_NEWLINE);
386 return CMD_WARNING;
387 }
388
389 actx = sgsn_apn_ctx_find_alloc(apn_str, imsi_prefix);
390 if (!actx) {
391 vty_out(vty, "%% unable to create APN context for %s/%s%s",
392 apn_str, imsi_prefix, VTY_NEWLINE);
393 return CMD_WARNING;
394 }
395
396 actx->ggsn = ggsn;
397
398 return CMD_SUCCESS;
399}
400
Harald Welted193cb32010-05-17 22:58:03 +0200401DEFUN(cfg_apn_ggsn, cfg_apn_ggsn_cmd,
402 "apn APNAME ggsn <0-255>",
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100403 APN_STR APN_GW_STR
404 "Select the GGSN to use when the APN gateway prefix matches\n"
405 "The GGSN id")
Harald Welted193cb32010-05-17 22:58:03 +0200406{
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100407
408 return add_apn_ggsn_mapping(vty, argv[0], "", atoi(argv[1]));
Harald Welted193cb32010-05-17 22:58:03 +0200409}
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100410
411DEFUN(cfg_apn_imsi_ggsn, cfg_apn_imsi_ggsn_cmd,
412 "apn APNAME imsi-prefix IMSIPRE ggsn <0-255>",
413 APN_STR APN_GW_STR
414 "Restrict rule to a certain IMSI prefix\n"
415 "An IMSI prefix\n"
416 "Select the GGSN to use when APN gateway and IMSI prefix match\n"
417 "The GGSN id")
418{
419
420 return add_apn_ggsn_mapping(vty, argv[0], argv[1], atoi(argv[2]));
421}
Harald Welted193cb32010-05-17 22:58:03 +0200422
423const struct value_string gprs_mm_st_strs[] = {
424 { GMM_DEREGISTERED, "DEREGISTERED" },
425 { GMM_COMMON_PROC_INIT, "COMMON PROCEDURE (INIT)" },
426 { GMM_REGISTERED_NORMAL, "REGISTERED (NORMAL)" },
Harald Weltebffeff82010-06-09 15:50:45 +0200427 { GMM_REGISTERED_SUSPENDED, "REGISTERED (SUSPENDED)" },
Harald Welted193cb32010-05-17 22:58:03 +0200428 { GMM_DEREGISTERED_INIT, "DEREGISTERED (INIT)" },
429 { 0, NULL }
430};
431
Maxc005db72017-10-27 18:43:29 +0200432char *sgsn_gtp_ntoa(struct ul16_t *ul)
Harald Welte471ac7d2016-12-15 19:48:58 +0100433{
Max8492c202017-12-05 17:28:15 +0100434 struct in_addr ia;
435
436 if (gsna2in_addr(&ia, ul) != 0)
Harald Welte471ac7d2016-12-15 19:48:58 +0100437 return "UNKNOWN";
Max8492c202017-12-05 17:28:15 +0100438
439 return inet_ntoa(ia);
Harald Welte471ac7d2016-12-15 19:48:58 +0100440}
441
Harald Welted193cb32010-05-17 22:58:03 +0200442static void vty_dump_pdp(struct vty *vty, const char *pfx,
443 struct sgsn_pdp_ctx *pdp)
444{
Jacob Erlbeck99985b52014-10-13 10:32:00 +0200445 const char *imsi = pdp->mm ? pdp->mm->imsi : "(detaching)";
Harald Welte471ac7d2016-12-15 19:48:58 +0100446 vty_out(vty, "%sPDP Context IMSI: %s, SAPI: %u, NSAPI: %u, TI: %u%s",
447 pfx, imsi, pdp->sapi, pdp->nsapi, pdp->ti, VTY_NEWLINE);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200448 if (pdp->lib) {
Max7933d962017-10-19 16:52:30 +0200449 char apnbuf[APN_MAXLEN + 1];
Harald Weltedfbd2c82017-08-13 00:56:45 +0200450 vty_out(vty, "%s APN: %s%s", pfx,
Max7933d962017-10-19 16:52:30 +0200451 osmo_apn_to_str(apnbuf, pdp->lib->apn_use.v, pdp->lib->apn_use.l),
Harald Weltedfbd2c82017-08-13 00:56:45 +0200452 VTY_NEWLINE);
453 vty_out(vty, "%s PDP Address: %s%s", pfx,
454 gprs_pdpaddr2str(pdp->lib->eua.v, pdp->lib->eua.l),
455 VTY_NEWLINE);
456 vty_out(vty, "%s GTP Local Control(%s / TEIC: 0x%08x) ", pfx,
Maxc005db72017-10-27 18:43:29 +0200457 sgsn_gtp_ntoa(&pdp->lib->gsnlc), pdp->lib->teic_own);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200458 vty_out(vty, "Data(%s / TEID: 0x%08x)%s",
Maxc005db72017-10-27 18:43:29 +0200459 sgsn_gtp_ntoa(&pdp->lib->gsnlu), pdp->lib->teid_own, VTY_NEWLINE);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200460 vty_out(vty, "%s GTP Remote Control(%s / TEIC: 0x%08x) ", pfx,
Maxc005db72017-10-27 18:43:29 +0200461 sgsn_gtp_ntoa(&pdp->lib->gsnrc), pdp->lib->teic_gn);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200462 vty_out(vty, "Data(%s / TEID: 0x%08x)%s",
Maxc005db72017-10-27 18:43:29 +0200463 sgsn_gtp_ntoa(&pdp->lib->gsnru), pdp->lib->teid_gn, VTY_NEWLINE);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200464 }
Harald Welte471ac7d2016-12-15 19:48:58 +0100465
Harald Welteefbdee92010-06-10 00:20:12 +0200466 vty_out_rate_ctr_group(vty, " ", pdp->ctrg);
Harald Welted193cb32010-05-17 22:58:03 +0200467}
468
469static void vty_dump_mmctx(struct vty *vty, const char *pfx,
470 struct sgsn_mm_ctx *mm, int pdp)
471{
472 vty_out(vty, "%sMM Context for IMSI %s, IMEI %s, P-TMSI %08x%s",
473 pfx, mm->imsi, mm->imei, mm->p_tmsi, VTY_NEWLINE);
Holger Hans Peter Freyther8ee13e22015-05-18 10:00:03 +0200474 vty_out(vty, "%s MSISDN: %s, TLLI: %08x%s HLR: %s",
Harald Weltef97ee042015-12-25 19:12:21 +0100475 pfx, mm->msisdn, mm->gb.tlli, mm->hlr, VTY_NEWLINE);
Harald Welted193cb32010-05-17 22:58:03 +0200476 vty_out(vty, "%s MM State: %s, Routeing Area: %u-%u-%u-%u, "
477 "Cell ID: %u%s", pfx,
Alexander Couzens4f8da6d2017-01-31 15:34:26 +0100478 get_value_string(gprs_mm_st_strs, mm->gmm_state),
Harald Welted193cb32010-05-17 22:58:03 +0200479 mm->ra.mcc, mm->ra.mnc, mm->ra.lac, mm->ra.rac,
Harald Weltef97ee042015-12-25 19:12:21 +0100480 mm->gb.cell_id, VTY_NEWLINE);
Harald Welted193cb32010-05-17 22:58:03 +0200481
Harald Welte8acd88f2010-05-18 10:57:45 +0200482 vty_out_rate_ctr_group(vty, " ", mm->ctrg);
483
Harald Welted193cb32010-05-17 22:58:03 +0200484 if (pdp) {
485 struct sgsn_pdp_ctx *pdp;
486
487 llist_for_each_entry(pdp, &mm->pdp_list, list)
488 vty_dump_pdp(vty, " ", pdp);
489 }
490}
491
492DEFUN(show_sgsn, show_sgsn_cmd, "show sgsn",
493 SHOW_STR "Display information about the SGSN")
494{
Jacob Erlbeck80547992014-12-19 19:19:46 +0100495 if (sgsn->gsup_client) {
496 struct ipa_client_conn *link = sgsn->gsup_client->link;
497 vty_out(vty,
498 " Remote authorization: %sconnected to %s:%d via GSUP%s",
499 sgsn->gsup_client->is_connected ? "" : "not ",
500 link->addr, link->port,
501 VTY_NEWLINE);
502 }
Maxbaabc682017-10-20 13:39:57 +0200503 if (sgsn->gsn)
504 vty_out(vty, " GSN: signalling %s, user traffic %s%s",
505 inet_ntoa(sgsn->gsn->gsnc), inet_ntoa(sgsn->gsn->gsnu), VTY_NEWLINE);
506
Harald Welted193cb32010-05-17 22:58:03 +0200507 /* FIXME: statistics */
508 return CMD_SUCCESS;
509}
510
511#define MMCTX_STR "MM Context\n"
512#define INCLUDE_PDP_STR "Include PDP Context Information\n"
513
514#if 0
515DEFUN(show_mmctx_tlli, show_mmctx_tlli_cmd,
516 "show mm-context tlli HEX [pdp]",
517 SHOW_STR MMCTX_STR "Identify by TLLI\n" "TLLI\n" INCLUDE_PDP_STR)
518{
519 uint32_t tlli;
520 struct sgsn_mm_ctx *mm;
521
522 tlli = strtoul(argv[0], NULL, 16);
523 mm = sgsn_mm_ctx_by_tlli(tlli);
524 if (!mm) {
525 vty_out(vty, "No MM context for TLLI %08x%s",
526 tlli, VTY_NEWLINE);
527 return CMD_WARNING;
528 }
529 vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
530 return CMD_SUCCESS;
531}
532#endif
533
534DEFUN(swow_mmctx_imsi, show_mmctx_imsi_cmd,
535 "show mm-context imsi IMSI [pdp]",
536 SHOW_STR MMCTX_STR "Identify by IMSI\n" "IMSI of the MM Context\n"
537 INCLUDE_PDP_STR)
538{
539 struct sgsn_mm_ctx *mm;
540
541 mm = sgsn_mm_ctx_by_imsi(argv[0]);
542 if (!mm) {
543 vty_out(vty, "No MM context for IMSI %s%s",
544 argv[0], VTY_NEWLINE);
545 return CMD_WARNING;
546 }
547 vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
548 return CMD_SUCCESS;
549}
550
551DEFUN(swow_mmctx_all, show_mmctx_all_cmd,
552 "show mm-context all [pdp]",
553 SHOW_STR MMCTX_STR "All MM Contexts\n" INCLUDE_PDP_STR)
554{
555 struct sgsn_mm_ctx *mm;
556
557 llist_for_each_entry(mm, &sgsn_mm_ctxts, list)
558 vty_dump_mmctx(vty, "", mm, argv[0] ? 1 : 0);
559
560 return CMD_SUCCESS;
561}
562
Harald Welted193cb32010-05-17 22:58:03 +0200563DEFUN(show_pdpctx_all, show_pdpctx_all_cmd,
564 "show pdp-context all",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100565 SHOW_STR "Display information on PDP Context\n" "Show everything\n")
Harald Welted193cb32010-05-17 22:58:03 +0200566{
567 struct sgsn_pdp_ctx *pdp;
568
569 llist_for_each_entry(pdp, &sgsn_pdp_ctxts, g_list)
570 vty_dump_pdp(vty, "", pdp);
571
572 return CMD_SUCCESS;
573}
Harald Welte288be162010-05-01 16:48:27 +0200574
Harald Welte7f6da482013-03-19 11:00:13 +0100575
576DEFUN(imsi_acl, cfg_imsi_acl_cmd,
577 "imsi-acl (add|del) IMSI",
578 "Access Control List of foreign IMSIs\n"
579 "Add IMSI to ACL\n"
580 "Remove IMSI from ACL\n"
581 "IMSI of subscriber\n")
582{
Philipp Maier6ee49d82017-02-28 16:53:07 +0100583 char imsi_sanitized[GSM23003_IMSI_MAX_DIGITS+1];
Harald Welte7f6da482013-03-19 11:00:13 +0100584 const char *op = argv[0];
Philipp Maier6ee49d82017-02-28 16:53:07 +0100585 const char *imsi = imsi_sanitized;
Harald Welte7f6da482013-03-19 11:00:13 +0100586 int rc;
587
Philipp Maier6ee49d82017-02-28 16:53:07 +0100588 /* Sanitize IMSI */
589 if (strlen(argv[1]) > GSM23003_IMSI_MAX_DIGITS) {
590 vty_out(vty, "%% IMSI (%s) too long -- ignored!%s",
591 argv[1], VTY_NEWLINE);
592 return CMD_WARNING;
593 }
594 memset(imsi_sanitized, '0', sizeof(imsi_sanitized));
595 strcpy(imsi_sanitized+GSM23003_IMSI_MAX_DIGITS-strlen(argv[1]),argv[1]);
596
Harald Welte7f6da482013-03-19 11:00:13 +0100597 if (!strcmp(op, "add"))
Jacob Erlbeck3b5d4072014-10-24 15:11:03 +0200598 rc = sgsn_acl_add(imsi, g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +0100599 else
Jacob Erlbeck3b5d4072014-10-24 15:11:03 +0200600 rc = sgsn_acl_del(imsi, g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +0100601
602 if (rc < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100603 vty_out(vty, "%% unable to %s ACL%s", op, VTY_NEWLINE);
Harald Welte7f6da482013-03-19 11:00:13 +0100604 return CMD_WARNING;
605 }
606
607 return CMD_SUCCESS;
608}
609
Max93408ae2016-06-28 14:10:16 +0200610DEFUN(cfg_encrypt, cfg_encrypt_cmd,
611 "encryption (GEA0|GEA1|GEA2|GEA3|GEA4)",
612 "Set encryption algorithm for SGSN\n"
613 "Use GEA0 (no encryption)\n"
614 "Use GEA1\nUse GEA2\nUse GEA3\nUse GEA4\n")
615{
Max93408ae2016-06-28 14:10:16 +0200616 enum gprs_ciph_algo c = get_string_value(gprs_cipher_names, argv[0]);
Max086067f2017-05-02 13:03:28 +0200617 if (c != GPRS_ALGO_GEA0) {
618 if (!gprs_cipher_supported(c)) {
619 vty_out(vty, "%% cipher %s is unsupported in current version%s", argv[0], VTY_NEWLINE);
620 return CMD_WARNING;
621 }
622
623 if (!g_cfg->require_authentication) {
624 vty_out(vty, "%% unable to use encryption %s without authentication: please adjust auth-policy%s",
625 argv[0], VTY_NEWLINE);
626 return CMD_WARNING;
627 }
Max93408ae2016-06-28 14:10:16 +0200628 }
629
630 g_cfg->cipher = c;
631
632 return CMD_SUCCESS;
633}
634
Harald Welte3dfb5492013-03-19 11:48:54 +0100635DEFUN(cfg_auth_policy, cfg_auth_policy_cmd,
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100636 "auth-policy (accept-all|closed|acl-only|remote)",
Harald Welte3dfb5492013-03-19 11:48:54 +0100637 "Autorization Policy of SGSN\n"
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100638 "Accept all IMSIs (DANGEROUS)\n"
639 "Accept only home network subscribers or those in the ACL\n"
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100640 "Accept only subscribers in the ACL\n"
641 "Use remote subscription data only (HLR)\n")
Harald Welte3dfb5492013-03-19 11:48:54 +0100642{
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100643 int val = get_string_value(sgsn_auth_pol_strs, argv[0]);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100644 OSMO_ASSERT(val >= SGSN_AUTH_POLICY_OPEN && val <= SGSN_AUTH_POLICY_REMOTE);
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100645 g_cfg->auth_policy = val;
Jacob Erlbeck9d4f46c2014-12-17 13:20:08 +0100646 g_cfg->require_authentication = (val == SGSN_AUTH_POLICY_REMOTE);
Jacob Erlbeck771573c2014-12-19 18:08:48 +0100647 g_cfg->require_update_location = (val == SGSN_AUTH_POLICY_REMOTE);
Harald Welte3dfb5492013-03-19 11:48:54 +0100648
649 return CMD_SUCCESS;
650}
651
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100652/* Subscriber */
Neels Hofmeyr396f2e62017-09-04 15:13:25 +0200653#include <osmocom/sgsn/gprs_subscriber.h>
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100654
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100655static void subscr_dump_full_vty(struct vty *vty, struct gprs_subscr *gsub, int pending)
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100656{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100657#if 0
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100658 char expire_time[200];
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100659#endif
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100660 struct gsm_auth_tuple *at;
661 int at_idx;
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100662 struct sgsn_subscriber_pdp_data *pdp;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100663
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100664 vty_out(vty, " Authorized: %d%s",
665 gsub->authorized, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100666 vty_out(vty, " LAC: %d/0x%x%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100667 gsub->lac, gsub->lac, VTY_NEWLINE);
668 vty_out(vty, " IMSI: %s%s", gsub->imsi, VTY_NEWLINE);
669 if (gsub->tmsi != GSM_RESERVED_TMSI)
670 vty_out(vty, " TMSI: %08X%s", gsub->tmsi,
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100671 VTY_NEWLINE);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100672 if (gsub->sgsn_data->msisdn_len > 0)
Holger Hans Peter Freytherf7b38262015-04-23 16:58:33 -0400673 vty_out(vty, " MSISDN (BCD): %s%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100674 osmo_hexdump(gsub->sgsn_data->msisdn,
675 gsub->sgsn_data->msisdn_len),
Holger Hans Peter Freytherf7b38262015-04-23 16:58:33 -0400676 VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100677
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100678 if (strlen(gsub->imei) > 0)
679 vty_out(vty, " IMEI: %s%s", gsub->imei, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100680
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100681 for (at_idx = 0; at_idx < ARRAY_SIZE(gsub->sgsn_data->auth_triplets);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100682 at_idx++) {
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100683 at = &gsub->sgsn_data->auth_triplets[at_idx];
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100684 if (at->key_seq == GSM_KEY_SEQ_INVAL)
685 continue;
686
687 vty_out(vty, " A3A8 tuple (used %d times): ",
688 at->use_count);
Harald Welte89837d42016-05-06 23:28:11 +0200689 vty_out(vty, " CKSN: %d, ",
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100690 at->key_seq);
Harald Welte89837d42016-05-06 23:28:11 +0200691 if (at->vec.auth_types & OSMO_AUTH_TYPE_GSM) {
692 vty_out(vty, "RAND: %s, ",
693 osmo_hexdump(at->vec.rand,
694 sizeof(at->vec.rand)));
695 vty_out(vty, "SRES: %s, ",
696 osmo_hexdump(at->vec.sres,
697 sizeof(at->vec.sres)));
698 vty_out(vty, "Kc: %s%s",
699 osmo_hexdump(at->vec.kc,
700 sizeof(at->vec.kc)), VTY_NEWLINE);
701 }
702 if (at->vec.auth_types & OSMO_AUTH_TYPE_UMTS) {
703 vty_out(vty, " AUTN: %s, ",
704 osmo_hexdump(at->vec.autn,
705 sizeof(at->vec.autn)));
706 vty_out(vty, "RES: %s, ",
707 osmo_hexdump(at->vec.res, at->vec.res_len));
708 vty_out(vty, "IK: %s, ",
709 osmo_hexdump(at->vec.ik, sizeof(at->vec.ik)));
710 vty_out(vty, "CK: %s, ",
711 osmo_hexdump(at->vec.ck, sizeof(at->vec.ck)));
712 }
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100713 }
714
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100715 llist_for_each_entry(pdp, &gsub->sgsn_data->pdp_list, list) {
Holger Hans Peter Freytherd05e0692015-04-23 16:59:04 -0400716 vty_out(vty, " PDP info: Id: %d, Type: 0x%04x, APN: '%s' QoS: %s%s",
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100717 pdp->context_id, pdp->pdp_type, pdp->apn_str,
Holger Hans Peter Freytherd05e0692015-04-23 16:59:04 -0400718 osmo_hexdump(pdp->qos_subscribed, pdp->qos_subscribed_len),
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100719 VTY_NEWLINE);
720 }
721
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100722#if 0
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100723 /* print the expiration time of a subscriber */
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100724 if (gsub->expire_lu) {
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100725 strftime(expire_time, sizeof(expire_time),
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100726 "%a, %d %b %Y %T %z", localtime(&gsub->expire_lu));
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100727 expire_time[sizeof(expire_time) - 1] = '\0';
728 vty_out(vty, " Expiration Time: %s%s", expire_time, VTY_NEWLINE);
729 }
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100730#endif
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100731
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100732 if (gsub->flags)
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100733 vty_out(vty, " Flags: %s%s%s%s%s%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100734 gsub->flags & GPRS_SUBSCRIBER_FIRST_CONTACT ?
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100735 "FIRST_CONTACT " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100736 gsub->flags & GPRS_SUBSCRIBER_CANCELLED ?
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100737 "CANCELLED " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100738 gsub->flags & GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING ?
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100739 "UPDATE_LOCATION_PENDING " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100740 gsub->flags & GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING ?
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100741 "AUTH_INFO_PENDING " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100742 gsub->flags & GPRS_SUBSCRIBER_ENABLE_PURGE ?
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100743 "ENABLE_PURGE " : "",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100744 VTY_NEWLINE);
745
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100746 vty_out(vty, " Use count: %u%s", gsub->use_count, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100747}
748
749DEFUN(show_subscr_cache,
750 show_subscr_cache_cmd,
751 "show subscriber cache",
752 SHOW_STR "Show information about subscribers\n"
753 "Display contents of subscriber cache\n")
754{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100755 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100756
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100757 llist_for_each_entry(subscr, gprs_subscribers, entry) {
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100758 vty_out(vty, " Subscriber:%s", VTY_NEWLINE);
759 subscr_dump_full_vty(vty, subscr, 0);
760 }
761
762 return CMD_SUCCESS;
763}
764
765#define UPDATE_SUBSCR_STR "update-subscriber imsi IMSI "
766#define UPDATE_SUBSCR_HELP "Update subscriber list\n" \
767 "Use the IMSI to select the subscriber\n" \
768 "The IMSI\n"
769
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100770#define UPDATE_SUBSCR_INSERT_HELP "Insert data into the subscriber record\n"
771
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100772DEFUN(update_subscr_insert_auth_triplet, update_subscr_insert_auth_triplet_cmd,
773 UPDATE_SUBSCR_STR "insert auth-triplet <1-5> sres SRES rand RAND kc KC",
774 UPDATE_SUBSCR_HELP
775 UPDATE_SUBSCR_INSERT_HELP
776 "Update authentication triplet\n"
777 "Triplet index\n"
778 "Set SRES value\nSRES value (4 byte) in hex\n"
779 "Set RAND value\nRAND value (16 byte) in hex\n"
780 "Set Kc value\nKc value (8 byte) in hex\n")
781{
782 const char *imsi = argv[0];
783 const int cksn = atoi(argv[1]) - 1;
784 const char *sres_str = argv[2];
785 const char *rand_str = argv[3];
786 const char *kc_str = argv[4];
787 struct gsm_auth_tuple at = {0,};
788
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100789 struct gprs_subscr *subscr;
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100790
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100791 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100792 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100793 vty_out(vty, "%% unable get subscriber record for %s%s",
794 imsi, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100795 return CMD_WARNING;
796 }
797
798 OSMO_ASSERT(subscr->sgsn_data);
799
Harald Welte121e9a42016-04-20 13:13:19 +0200800 if (osmo_hexparse(sres_str, &at.vec.sres[0], sizeof(at.vec.sres)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100801 vty_out(vty, "%% invalid SRES value '%s'%s",
802 sres_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100803 goto failed;
804 }
Harald Welte121e9a42016-04-20 13:13:19 +0200805 if (osmo_hexparse(rand_str, &at.vec.rand[0], sizeof(at.vec.rand)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100806 vty_out(vty, "%% invalid RAND value '%s'%s",
807 rand_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100808 goto failed;
809 }
Harald Welte121e9a42016-04-20 13:13:19 +0200810 if (osmo_hexparse(kc_str, &at.vec.kc[0], sizeof(at.vec.kc)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100811 vty_out(vty, "%% invalid Kc value '%s'%s",
812 kc_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100813 goto failed;
814 }
815 at.key_seq = cksn;
816
817 subscr->sgsn_data->auth_triplets[cksn] = at;
818 subscr->sgsn_data->auth_triplets_updated = 1;
819
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100820 gprs_subscr_put(subscr);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100821
822 return CMD_SUCCESS;
823
824failed:
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100825 gprs_subscr_put(subscr);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100826 return CMD_SUCCESS;
827}
828
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100829DEFUN(update_subscr_cancel, update_subscr_cancel_cmd,
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100830 UPDATE_SUBSCR_STR "cancel (update-procedure|subscription-withdraw)",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100831 UPDATE_SUBSCR_HELP
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100832 "Cancel (remove) subscriber record\n"
833 "The MS moved to another SGSN\n"
834 "The subscription is no longer valid\n")
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100835{
836 const char *imsi = argv[0];
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100837 const char *cancel_type = argv[1];
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100838
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100839 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100840
841 subscr = gprs_subscr_get_by_imsi(imsi);
842 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100843 vty_out(vty, "%% no subscriber record for %s%s",
844 imsi, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100845 return CMD_WARNING;
846 }
847
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100848 if (strcmp(cancel_type, "update-procedure") == 0)
849 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
850 else
851 subscr->sgsn_data->error_cause = GMM_CAUSE_IMPL_DETACHED;
852
Jacob Erlbeck37139e52015-01-23 13:52:55 +0100853 gprs_subscr_cancel(subscr);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100854 gprs_subscr_put(subscr);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100855
856 return CMD_SUCCESS;
857}
858
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100859DEFUN(update_subscr_create, update_subscr_create_cmd,
860 UPDATE_SUBSCR_STR "create",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100861 UPDATE_SUBSCR_HELP
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100862 "Create a subscriber entry\n")
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100863{
864 const char *imsi = argv[0];
865
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100866 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100867
868 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100869 if (subscr) {
870 vty_out(vty, "%% subscriber record already exists for %s%s",
871 imsi, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100872 return CMD_WARNING;
873 }
874
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100875 subscr = gprs_subscr_get_or_create(imsi);
876 subscr->keep_in_ram = 1;
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100877 gprs_subscr_put(subscr);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100878
879 return CMD_SUCCESS;
880}
881
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100882DEFUN(update_subscr_destroy, update_subscr_destroy_cmd,
883 UPDATE_SUBSCR_STR "destroy",
884 UPDATE_SUBSCR_HELP
885 "Destroy a subscriber entry\n")
886{
887 const char *imsi = argv[0];
888
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100889 struct gprs_subscr *subscr;
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100890
891 subscr = gprs_subscr_get_by_imsi(imsi);
892 if (!subscr) {
893 vty_out(vty, "%% subscriber record does not exist for %s%s",
894 imsi, VTY_NEWLINE);
895 return CMD_WARNING;
896 }
897
898 subscr->keep_in_ram = 0;
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100899 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100900 gprs_subscr_cancel(subscr);
901 if (subscr->use_count > 1)
902 vty_out(vty, "%% subscriber is still in use%s",
903 VTY_NEWLINE);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100904 gprs_subscr_put(subscr);
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100905
906 return CMD_SUCCESS;
907}
908
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100909#define UL_ERR_STR "system-failure|data-missing|unexpected-data-value|" \
910 "unknown-subscriber|roaming-not-allowed"
911
912#define UL_ERR_HELP \
913 "Force error code SystemFailure\n" \
914 "Force error code DataMissing\n" \
915 "Force error code UnexpectedDataValue\n" \
916 "Force error code UnknownSubscriber\n" \
917 "Force error code RoamingNotAllowed\n"
918
919DEFUN(update_subscr_update_location_result, update_subscr_update_location_result_cmd,
920 UPDATE_SUBSCR_STR "update-location-result (ok|" UL_ERR_STR ")",
921 UPDATE_SUBSCR_HELP
922 "Complete the update location procedure\n"
923 "The update location request succeeded\n"
924 UL_ERR_HELP)
925{
926 const char *imsi = argv[0];
927 const char *ret_code_str = argv[1];
928
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100929 struct gprs_subscr *subscr;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100930
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100931 const struct value_string cause_mapping[] = {
932 { GMM_CAUSE_NET_FAIL, "system-failure" },
933 { GMM_CAUSE_INV_MAND_INFO, "data-missing" },
934 { GMM_CAUSE_PROTO_ERR_UNSPEC, "unexpected-data-value" },
935 { GMM_CAUSE_IMSI_UNKNOWN, "unknown-subscriber" },
936 { GMM_CAUSE_GPRS_NOTALLOWED, "roaming-not-allowed" },
937 { 0, NULL }
938 };
939
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100940 subscr = gprs_subscr_get_by_imsi(imsi);
941 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100942 vty_out(vty, "%% unable to get subscriber record for %s%s",
943 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100944 return CMD_WARNING;
945 }
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100946
947 if (strcmp(ret_code_str, "ok") == 0) {
948 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100949 subscr->authorized = 1;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100950 } else {
951 subscr->sgsn_data->error_cause =
952 get_string_value(cause_mapping, ret_code_str);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100953 subscr->authorized = 0;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100954 }
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100955
956 gprs_subscr_update(subscr);
957
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100958 gprs_subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100959
960 return CMD_SUCCESS;
961}
962
963DEFUN(update_subscr_update_auth_info, update_subscr_update_auth_info_cmd,
964 UPDATE_SUBSCR_STR "update-auth-info",
965 UPDATE_SUBSCR_HELP
966 "Complete the send authentication info procedure\n")
967{
968 const char *imsi = argv[0];
969
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100970 struct gprs_subscr *subscr;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100971
972 subscr = gprs_subscr_get_by_imsi(imsi);
973 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100974 vty_out(vty, "%% unable to get subscriber record for %s%s",
975 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100976 return CMD_WARNING;
977 }
978
979 gprs_subscr_update_auth_info(subscr);
980
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100981 gprs_subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100982
983 return CMD_SUCCESS;
984}
985
Jacob Erlbeck39f040d2014-12-18 12:46:47 +0100986DEFUN(cfg_gsup_remote_ip, cfg_gsup_remote_ip_cmd,
987 "gsup remote-ip A.B.C.D",
988 "GSUP Parameters\n"
989 "Set the IP address of the remote GSUP server\n"
990 "IPv4 Address\n")
991{
992 inet_aton(argv[0], &g_cfg->gsup_server_addr.sin_addr);
993
994 return CMD_SUCCESS;
995}
996
997DEFUN(cfg_gsup_remote_port, cfg_gsup_remote_port_cmd,
998 "gsup remote-port <0-65535>",
999 "GSUP Parameters\n"
1000 "Set the TCP port of the remote GSUP server\n"
1001 "Remote TCP port\n")
1002{
1003 g_cfg->gsup_server_port = atoi(argv[0]);
1004
1005 return CMD_SUCCESS;
1006}
1007
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001008DEFUN(cfg_gsup_oap_id, cfg_gsup_oap_id_cmd,
1009 "gsup oap-id <0-65535>",
1010 "GSUP Parameters\n"
1011 "Set the SGSN's OAP client ID\nOAP client ID (0 == disabled)\n")
1012{
1013 /* VTY ensures range */
1014 g_cfg->oap.client_id = (uint16_t)atoi(argv[0]);
1015 return CMD_SUCCESS;
1016}
1017
1018DEFUN(cfg_gsup_oap_k, cfg_gsup_oap_k_cmd,
1019 "gsup oap-k K",
1020 "GSUP Parameters\n"
1021 "Set the OAP shared secret K\nK value (16 byte) hex\n")
1022{
1023 const char *k = argv[0];
1024
1025 g_cfg->oap.secret_k_present = 0;
1026
1027 if ((!k) || (strlen(k) == 0))
1028 goto disable;
1029
1030 int k_len = osmo_hexparse(k,
1031 g_cfg->oap.secret_k,
1032 sizeof(g_cfg->oap.secret_k));
1033 if (k_len != 16) {
1034 vty_out(vty, "%% need exactly 16 octets for oap-k, got %d.%s",
1035 k_len, VTY_NEWLINE);
1036 goto disable;
1037 }
1038
1039 g_cfg->oap.secret_k_present = 1;
1040 return CMD_SUCCESS;
1041
1042disable:
1043 if (g_cfg->oap.client_id > 0) {
1044 vty_out(vty, "%% OAP client ID set, but invalid oap-k value disables OAP.%s",
1045 VTY_NEWLINE);
1046 return CMD_WARNING;
1047 }
1048 return CMD_SUCCESS;
1049}
1050
1051DEFUN(cfg_gsup_oap_opc, cfg_gsup_oap_opc_cmd,
1052 "gsup oap-opc OPC",
1053 "GSUP Parameters\n"
1054 "Set the OAP shared secret OPC\nOPC value (16 byte) hex\n")
1055{
1056 const char *opc = argv[0];
1057
1058 g_cfg->oap.secret_opc_present = 0;
1059
1060 if ((!opc) || (strlen(opc) == 0))
1061 goto disable;
1062
1063 int opc_len = osmo_hexparse(opc,
1064 g_cfg->oap.secret_opc,
1065 sizeof(g_cfg->oap.secret_opc));
1066 if (opc_len != 16) {
1067 vty_out(vty, "%% need exactly 16 octets for oap-opc, got %d.%s",
1068 opc_len, VTY_NEWLINE);
1069 goto disable;
1070 }
1071
1072 g_cfg->oap.secret_opc_present = 1;
1073 return CMD_SUCCESS;
1074
1075disable:
1076 if (g_cfg->oap.client_id > 0) {
1077 vty_out(vty, "%% OAP client ID set, but invalid oap-opc value disables OAP.%s",
1078 VTY_NEWLINE);
1079 return CMD_WARNING;
1080 }
1081 return CMD_SUCCESS;
1082}
1083
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001084DEFUN(cfg_apn_name, cfg_apn_name_cmd,
1085 "access-point-name NAME",
1086 "Configure a global list of allowed APNs\n"
1087 "Add this NAME to the list\n")
1088{
1089 return add_apn_ggsn_mapping(vty, argv[0], "", 0);
1090}
1091
1092DEFUN(cfg_no_apn_name, cfg_no_apn_name_cmd,
1093 "no access-point-name NAME",
1094 NO_STR "Configure a global list of allowed APNs\n"
1095 "Remove entry with NAME\n")
1096{
1097 struct apn_ctx *apn_ctx = sgsn_apn_ctx_by_name(argv[0], "");
1098 if (!apn_ctx)
1099 return CMD_SUCCESS;
1100
1101 sgsn_apn_ctx_free(apn_ctx);
1102 return CMD_SUCCESS;
1103}
1104
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001105DEFUN(cfg_cdr_filename, cfg_cdr_filename_cmd,
1106 "cdr filename NAME",
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +01001107 "CDR\nEnable saving CDR to filename\nname\n")
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001108{
1109 talloc_free(g_cfg->cdr.filename);
1110 g_cfg->cdr.filename = talloc_strdup(tall_vty_ctx, argv[0]);
1111 return CMD_SUCCESS;
1112}
1113
1114DEFUN(cfg_no_cdr_filename, cfg_no_cdr_filename_cmd,
1115 "no cdr filename",
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +01001116 NO_STR "CDR\nDisable saving CDR to file\n")
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001117{
1118 talloc_free(g_cfg->cdr.filename);
1119 g_cfg->cdr.filename = NULL;
1120 return CMD_SUCCESS;
1121}
1122
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +01001123DEFUN(cfg_cdr_trap, cfg_cdr_trap_cmd,
1124 "cdr trap",
1125 "CDR\nEnable sending CDR via TRAP CTRL messages\n")
1126{
1127 g_cfg->cdr.trap = true;
1128 return CMD_SUCCESS;
1129}
1130
1131DEFUN(cfg_no_cdr_trap, cfg_no_cdr_trap_cmd,
1132 "no cdr trap",
1133 NO_STR "CDR\nDisable sending CDR via TRAP CTRL messages\n")
1134{
1135 g_cfg->cdr.trap = false;
1136 return CMD_SUCCESS;
1137}
1138
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001139DEFUN(cfg_cdr_interval, cfg_cdr_interval_cmd,
1140 "cdr interval <1-2147483647>",
1141 "CDR\nPDP periodic log interval\nSeconds\n")
1142{
1143 g_cfg->cdr.interval = atoi(argv[0]);
1144 return CMD_SUCCESS;
1145}
1146
Philippf1f34362016-08-26 17:00:21 +02001147#define COMPRESSION_STR "Configure compression\n"
1148DEFUN(cfg_no_comp_rfc1144, cfg_no_comp_rfc1144_cmd,
1149 "no compression rfc1144",
1150 NO_STR COMPRESSION_STR "disable rfc1144 TCP/IP header compression\n")
1151{
1152 g_cfg->pcomp_rfc1144.active = 0;
1153 g_cfg->pcomp_rfc1144.passive = 0;
1154 return CMD_SUCCESS;
1155}
1156
1157DEFUN(cfg_comp_rfc1144, cfg_comp_rfc1144_cmd,
1158 "compression rfc1144 active slots <1-256>",
1159 COMPRESSION_STR
1160 "RFC1144 Header compresion scheme\n"
1161 "Compression is actively proposed\n"
1162 "Number of compression state slots\n"
1163 "Number of compression state slots\n")
1164{
1165 g_cfg->pcomp_rfc1144.active = 1;
1166 g_cfg->pcomp_rfc1144.passive = 1;
1167 g_cfg->pcomp_rfc1144.s01 = atoi(argv[0]) - 1;
1168 return CMD_SUCCESS;
1169}
1170
1171DEFUN(cfg_comp_rfc1144p, cfg_comp_rfc1144p_cmd,
1172 "compression rfc1144 passive",
1173 COMPRESSION_STR
1174 "RFC1144 Header compresion scheme\n"
1175 "Compression is available on request\n")
1176{
1177 g_cfg->pcomp_rfc1144.active = 0;
1178 g_cfg->pcomp_rfc1144.passive = 1;
1179 return CMD_SUCCESS;
1180}
1181
Philipp73f83d52016-09-02 13:38:01 +02001182DEFUN(cfg_no_comp_v42bis, cfg_no_comp_v42bis_cmd,
1183 "no compression v42bis",
1184 NO_STR COMPRESSION_STR "disable V.42bis data compression\n")
1185{
1186 g_cfg->dcomp_v42bis.active = 0;
1187 g_cfg->dcomp_v42bis.passive = 0;
1188 return CMD_SUCCESS;
1189}
1190
1191DEFUN(cfg_comp_v42bis, cfg_comp_v42bis_cmd,
1192 "compression v42bis active direction (ms|sgsn|both) codewords <512-65535> strlen <6-250>",
1193 COMPRESSION_STR
1194 "V.42bis data compresion scheme\n"
1195 "Compression is actively proposed\n"
1196 "Direction in which the compression shall be active (p0)\n"
1197 "Compress ms->sgsn direction only\n"
1198 "Compress sgsn->ms direction only\n"
1199 "Both directions\n"
1200 "Number of codewords (p1)\n"
1201 "Number of codewords\n"
1202 "Maximum string length (p2)\n" "Maximum string length\n")
1203{
1204 g_cfg->dcomp_v42bis.active = 1;
1205 g_cfg->dcomp_v42bis.passive = 1;
1206
1207 switch (argv[0][0]) {
1208 case 'm':
1209 g_cfg->dcomp_v42bis.p0 = 1;
1210 break;
1211 case 's':
1212 g_cfg->dcomp_v42bis.p0 = 2;
1213 break;
1214 case 'b':
1215 g_cfg->dcomp_v42bis.p0 = 3;
1216 break;
1217 }
1218
1219 g_cfg->dcomp_v42bis.p1 = atoi(argv[1]);
1220 g_cfg->dcomp_v42bis.p2 = atoi(argv[2]);
1221 return CMD_SUCCESS;
1222}
1223
1224DEFUN(cfg_comp_v42bisp, cfg_comp_v42bisp_cmd,
1225 "compression v42bis passive",
1226 COMPRESSION_STR
1227 "V.42bis data compresion scheme\n"
1228 "Compression is available on request\n")
1229{
1230 g_cfg->dcomp_v42bis.active = 0;
1231 g_cfg->dcomp_v42bis.passive = 1;
1232 return CMD_SUCCESS;
1233}
1234
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001235int sgsn_vty_init(struct sgsn_config *cfg)
Harald Welte288be162010-05-01 16:48:27 +02001236{
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001237 g_cfg = cfg;
1238
Harald Welted193cb32010-05-17 22:58:03 +02001239 install_element_ve(&show_sgsn_cmd);
1240 //install_element_ve(&show_mmctx_tlli_cmd);
1241 install_element_ve(&show_mmctx_imsi_cmd);
1242 install_element_ve(&show_mmctx_all_cmd);
1243 install_element_ve(&show_pdpctx_all_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001244 install_element_ve(&show_subscr_cache_cmd);
1245
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01001246 install_element(ENABLE_NODE, &update_subscr_insert_auth_triplet_cmd);
Jacob Erlbeckd9193432015-01-19 14:11:46 +01001247 install_element(ENABLE_NODE, &update_subscr_create_cmd);
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001248 install_element(ENABLE_NODE, &update_subscr_destroy_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001249 install_element(ENABLE_NODE, &update_subscr_cancel_cmd);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001250 install_element(ENABLE_NODE, &update_subscr_update_location_result_cmd);
1251 install_element(ENABLE_NODE, &update_subscr_update_auth_info_cmd);
Harald Welte288be162010-05-01 16:48:27 +02001252
1253 install_element(CONFIG_NODE, &cfg_sgsn_cmd);
1254 install_node(&sgsn_node, config_write_sgsn);
Harald Weltee300d002010-06-02 12:41:34 +02001255 install_element(SGSN_NODE, &cfg_sgsn_bind_addr_cmd);
Harald Welted193cb32010-05-17 22:58:03 +02001256 install_element(SGSN_NODE, &cfg_ggsn_remote_ip_cmd);
1257 //install_element(SGSN_NODE, &cfg_ggsn_remote_port_cmd);
1258 install_element(SGSN_NODE, &cfg_ggsn_gtp_version_cmd);
Harald Welte7f6da482013-03-19 11:00:13 +01001259 install_element(SGSN_NODE, &cfg_imsi_acl_cmd);
Harald Welte3dfb5492013-03-19 11:48:54 +01001260 install_element(SGSN_NODE, &cfg_auth_policy_cmd);
Max93408ae2016-06-28 14:10:16 +02001261 install_element(SGSN_NODE, &cfg_encrypt_cmd);
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001262 install_element(SGSN_NODE, &cfg_gsup_remote_ip_cmd);
1263 install_element(SGSN_NODE, &cfg_gsup_remote_port_cmd);
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001264 install_element(SGSN_NODE, &cfg_gsup_oap_id_cmd);
1265 install_element(SGSN_NODE, &cfg_gsup_oap_k_cmd);
1266 install_element(SGSN_NODE, &cfg_gsup_oap_opc_cmd);
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +01001267 install_element(SGSN_NODE, &cfg_apn_ggsn_cmd);
1268 install_element(SGSN_NODE, &cfg_apn_imsi_ggsn_cmd);
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001269 install_element(SGSN_NODE, &cfg_apn_name_cmd);
1270 install_element(SGSN_NODE, &cfg_no_apn_name_cmd);
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001271 install_element(SGSN_NODE, &cfg_cdr_filename_cmd);
1272 install_element(SGSN_NODE, &cfg_no_cdr_filename_cmd);
Pau Espin Pedrol2e9ea502017-11-29 14:01:35 +01001273 install_element(SGSN_NODE, &cfg_cdr_trap_cmd);
1274 install_element(SGSN_NODE, &cfg_no_cdr_trap_cmd);
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001275 install_element(SGSN_NODE, &cfg_cdr_interval_cmd);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001276 install_element(SGSN_NODE, &cfg_ggsn_dynamic_lookup_cmd);
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +08001277 install_element(SGSN_NODE, &cfg_grx_ggsn_cmd);
Harald Welte288be162010-05-01 16:48:27 +02001278
Harald Welte94508822015-08-15 19:08:21 +02001279 install_element(SGSN_NODE, &cfg_sgsn_T3312_cmd);
1280 install_element(SGSN_NODE, &cfg_sgsn_T3322_cmd);
1281 install_element(SGSN_NODE, &cfg_sgsn_T3350_cmd);
1282 install_element(SGSN_NODE, &cfg_sgsn_T3360_cmd);
1283 install_element(SGSN_NODE, &cfg_sgsn_T3370_cmd);
1284 install_element(SGSN_NODE, &cfg_sgsn_T3313_cmd);
1285 install_element(SGSN_NODE, &cfg_sgsn_T3314_cmd);
1286 install_element(SGSN_NODE, &cfg_sgsn_T3316_cmd);
1287 install_element(SGSN_NODE, &cfg_sgsn_T3385_cmd);
1288 install_element(SGSN_NODE, &cfg_sgsn_T3386_cmd);
1289 install_element(SGSN_NODE, &cfg_sgsn_T3395_cmd);
1290 install_element(SGSN_NODE, &cfg_sgsn_T3397_cmd);
1291
Philippf1f34362016-08-26 17:00:21 +02001292 install_element(SGSN_NODE, &cfg_no_comp_rfc1144_cmd);
1293 install_element(SGSN_NODE, &cfg_comp_rfc1144_cmd);
1294 install_element(SGSN_NODE, &cfg_comp_rfc1144p_cmd);
Philipp73f83d52016-09-02 13:38:01 +02001295 install_element(SGSN_NODE, &cfg_no_comp_v42bis_cmd);
1296 install_element(SGSN_NODE, &cfg_comp_v42bis_cmd);
1297 install_element(SGSN_NODE, &cfg_comp_v42bisp_cmd);
Neels Hofmeyr2188a772016-05-20 21:59:55 +02001298
1299#ifdef BUILD_IU
Neels Hofmeyra7a39472017-07-05 15:19:52 +02001300 ranap_iu_vty_init(SGSN_NODE, &g_cfg->iu.rab_assign_addr_enc);
Neels Hofmeyr2188a772016-05-20 21:59:55 +02001301#endif
Harald Welte288be162010-05-01 16:48:27 +02001302 return 0;
1303}
1304
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001305int sgsn_parse_config(const char *config_file)
Harald Welte288be162010-05-01 16:48:27 +02001306{
1307 int rc;
1308
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001309 /* make sure sgsn_vty_init() was called before this */
1310 OSMO_ASSERT(g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +01001311
Harald Welte94508822015-08-15 19:08:21 +02001312 g_cfg->timers.T3312 = GSM0408_T3312_SECS;
1313 g_cfg->timers.T3322 = GSM0408_T3322_SECS;
1314 g_cfg->timers.T3350 = GSM0408_T3350_SECS;
1315 g_cfg->timers.T3360 = GSM0408_T3360_SECS;
1316 g_cfg->timers.T3370 = GSM0408_T3370_SECS;
1317 g_cfg->timers.T3313 = GSM0408_T3313_SECS;
1318 g_cfg->timers.T3314 = GSM0408_T3314_SECS;
1319 g_cfg->timers.T3316 = GSM0408_T3316_SECS;
1320 g_cfg->timers.T3385 = GSM0408_T3385_SECS;
1321 g_cfg->timers.T3386 = GSM0408_T3386_SECS;
1322 g_cfg->timers.T3395 = GSM0408_T3395_SECS;
1323 g_cfg->timers.T3397 = GSM0408_T3397_SECS;
1324
Harald Weltedcccb182010-05-16 20:52:23 +02001325 rc = vty_read_config_file(config_file, NULL);
Harald Welte288be162010-05-01 16:48:27 +02001326 if (rc < 0) {
1327 fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
1328 return rc;
1329 }
1330
Neels Hofmeyr27355c92017-02-24 06:28:31 +01001331 if (g_cfg->auth_policy == SGSN_AUTH_POLICY_REMOTE
1332 && !(g_cfg->gsup_server_addr.sin_addr.s_addr
1333 && g_cfg->gsup_server_port)) {
1334 fprintf(stderr, "Configuration error:"
1335 " 'auth-policy remote' requires both"
1336 " 'gsup remote-ip' and 'gsup remote-port'\n");
1337 return -EINVAL;
1338 }
1339
Harald Welte288be162010-05-01 16:48:27 +02001340 return 0;
1341}