blob: 18828525d34b87b5918c2ecb9eafa2b43ccd8add [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>
47
Neels Hofmeyr2188a772016-05-20 21:59:55 +020048#include "../../bscconfig.h"
49
50#ifdef BUILD_IU
Neels Hofmeyra7a39472017-07-05 15:19:52 +020051#include <osmocom/ranap/iu_client.h>
Neels Hofmeyr2188a772016-05-20 21:59:55 +020052#endif
53
Neels Hofmeyree6cfdc2017-07-13 02:03:50 +020054extern void *tall_bsc_ctx;
55
Harald Welte288be162010-05-01 16:48:27 +020056static struct sgsn_config *g_cfg = NULL;
57
Jacob Erlbeck106f5472014-11-04 10:08:37 +010058const struct value_string sgsn_auth_pol_strs[] = {
59 { SGSN_AUTH_POLICY_OPEN, "accept-all" },
60 { SGSN_AUTH_POLICY_CLOSED, "closed" },
61 { SGSN_AUTH_POLICY_ACL_ONLY, "acl-only" },
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +010062 { SGSN_AUTH_POLICY_REMOTE, "remote" },
Jacob Erlbeck106f5472014-11-04 10:08:37 +010063 { 0, NULL }
64};
65
Harald Welte94508822015-08-15 19:08:21 +020066/* Section 11.2.2 / Table 11.3a GPRS Mobility management timers – MS side */
67#define GSM0408_T3312_SECS (10*60) /* periodic RAU interval, default 54min */
68
69/* Section 11.2.2 / Table 11.4 MM timers netwokr side */
70#define GSM0408_T3322_SECS 6 /* DETACH_REQ -> DETACH_ACC */
71#define GSM0408_T3350_SECS 6 /* waiting for ATT/RAU/TMSI COMPL */
72#define GSM0408_T3360_SECS 6 /* waiting for AUTH/CIPH RESP */
73#define GSM0408_T3370_SECS 6 /* waiting for ID RESP */
74
Alexander Couzens5ba6fb32017-01-31 18:04:27 +010075/* Section 11.2.2 / Table 11.4a MM timers network side */
Harald Welte94508822015-08-15 19:08:21 +020076#define GSM0408_T3313_SECS 30 /* waiting for paging response */
77#define GSM0408_T3314_SECS 44 /* force to STBY on expiry, Ready timer */
78#define GSM0408_T3316_SECS 44
79
80/* Section 11.3 / Table 11.2d Timers of Session Management - network side */
81#define GSM0408_T3385_SECS 8 /* wait for ACT PDP CTX REQ */
82#define GSM0408_T3386_SECS 8 /* wait for MODIFY PDP CTX ACK */
83#define GSM0408_T3395_SECS 8 /* wait for DEACT PDP CTX ACK */
84#define GSM0408_T3397_SECS 8 /* wait for DEACT AA PDP CTX ACK */
85
86#define DECLARE_TIMER(number, doc) \
87 DEFUN(cfg_sgsn_T##number, \
88 cfg_sgsn_T##number##_cmd, \
89 "timer t" #number " <0-65535>", \
90 "Configure GPRS Timers\n" \
Holger Hans Peter Freytherfe60cfb2015-11-02 12:55:07 +010091 doc "\nTimer Value in seconds\n") \
Harald Welte94508822015-08-15 19:08:21 +020092{ \
93 int value = atoi(argv[0]); \
94 \
95 if (value < 0 || value > 65535) { \
96 vty_out(vty, "Timer value %s out of range.%s", \
97 argv[0], VTY_NEWLINE); \
98 return CMD_WARNING; \
99 } \
100 \
101 g_cfg->timers.T##number = value; \
102 return CMD_SUCCESS; \
103}
104
105DECLARE_TIMER(3312, "Periodic RA Update timer (s)")
Neels Hofmeyr65482c92015-10-19 14:37:12 +0200106DECLARE_TIMER(3322, "Detach request -> accept timer (s)")
Harald Welte94508822015-08-15 19:08:21 +0200107DECLARE_TIMER(3350, "Waiting for ATT/RAU/TMSI_COMPL timer (s)")
108DECLARE_TIMER(3360, "Waiting for AUTH/CIPH response timer (s)")
109DECLARE_TIMER(3370, "Waiting for IDENTITY response timer (s)")
110
111DECLARE_TIMER(3313, "Waiting for paging response timer (s)")
112DECLARE_TIMER(3314, "Force to STANDBY on expiry timer (s)")
Holger Hans Peter Freytherfe60cfb2015-11-02 12:55:07 +0100113DECLARE_TIMER(3316, "AA-Ready timer (s)")
Harald Welte94508822015-08-15 19:08:21 +0200114
115DECLARE_TIMER(3385, "Wait for ACT PDP CTX REQ timer (s)")
116DECLARE_TIMER(3386, "Wait for MODIFY PDP CTX ACK timer (s)")
117DECLARE_TIMER(3395, "Wait for DEACT PDP CTX ACK timer (s)")
118DECLARE_TIMER(3397, "Wait for DEACT AA PDP CTX ACK timer (s)")
119
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100120
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200121#define GSM48_MAX_APN_LEN 102 /* 10.5.6.1 */
Neels Hofmeyr30f7bcb2015-11-08 20:34:47 +0100122/** Copy apn to a static buffer, replacing the length octets in apn_enc with '.'
123 * and terminating with a '\0'. Return the static buffer.
124 * len: the length of the encoded APN (which has no terminating zero).
125 */
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200126static char *gprs_apn2str(uint8_t *apn, unsigned int len)
127{
128 static char apnbuf[GSM48_MAX_APN_LEN+1];
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200129
130 if (!apn)
131 return "";
Harald Welte7e82b742017-08-12 13:43:54 +0200132 osmo_apn_to_str(apnbuf, apn, len);
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200133
134 return apnbuf+1;
135}
136
Holger Hans Peter Freythera2730302014-03-23 18:08:26 +0100137char *gprs_pdpaddr2str(uint8_t *pdpa, uint8_t len)
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200138{
139 static char str[INET6_ADDRSTRLEN + 10];
140
141 if (!pdpa || len < 2)
142 return "none";
143
144 switch (pdpa[0] & 0x0f) {
145 case PDP_TYPE_ORG_IETF:
146 switch (pdpa[1]) {
147 case PDP_TYPE_N_IETF_IPv4:
148 if (len < 2 + 4)
149 break;
150 strcpy(str, "IPv4 ");
151 inet_ntop(AF_INET, pdpa+2, str+5, sizeof(str)-5);
152 return str;
153 case PDP_TYPE_N_IETF_IPv6:
154 if (len < 2 + 8)
155 break;
156 strcpy(str, "IPv6 ");
157 inet_ntop(AF_INET6, pdpa+2, str+5, sizeof(str)-5);
158 return str;
159 default:
160 break;
161 }
162 break;
163 case PDP_TYPE_ORG_ETSI:
164 if (pdpa[1] == PDP_TYPE_N_ETSI_PPP)
165 return "PPP";
166 break;
167 default:
168 break;
169 }
170
171 return "invalid";
172}
173
Harald Welte288be162010-05-01 16:48:27 +0200174static struct cmd_node sgsn_node = {
175 SGSN_NODE,
Harald Welte570ce242012-08-17 13:16:10 +0200176 "%s(config-sgsn)# ",
Harald Welte288be162010-05-01 16:48:27 +0200177 1,
178};
179
180static int config_write_sgsn(struct vty *vty)
181{
Harald Welte77289c22010-05-18 14:32:29 +0200182 struct sgsn_ggsn_ctx *gctx;
Harald Welte7f6da482013-03-19 11:00:13 +0100183 struct imsi_acl_entry *acl;
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100184 struct apn_ctx *actx;
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800185 struct ares_addr_node *server;
Harald Welte288be162010-05-01 16:48:27 +0200186
187 vty_out(vty, "sgsn%s", VTY_NEWLINE);
188
Harald Weltee300d002010-06-02 12:41:34 +0200189 vty_out(vty, " gtp local-ip %s%s",
190 inet_ntoa(g_cfg->gtp_listenaddr.sin_addr), VTY_NEWLINE);
191
Harald Welted193cb32010-05-17 22:58:03 +0200192 llist_for_each_entry(gctx, &sgsn_ggsn_ctxts, list) {
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800193 if (gctx->id == UINT32_MAX)
194 continue;
195
Harald Welteff3bde82010-05-19 15:09:09 +0200196 vty_out(vty, " ggsn %u remote-ip %s%s", gctx->id,
Harald Welted193cb32010-05-17 22:58:03 +0200197 inet_ntoa(gctx->remote_addr), VTY_NEWLINE);
Harald Welteff3bde82010-05-19 15:09:09 +0200198 vty_out(vty, " ggsn %u gtp-version %u%s", gctx->id,
Harald Welted193cb32010-05-17 22:58:03 +0200199 gctx->gtp_version, VTY_NEWLINE);
Harald Welte288be162010-05-01 16:48:27 +0200200 }
201
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800202 if (sgsn->cfg.dynamic_lookup)
203 vty_out(vty, " ggsn dynamic%s", VTY_NEWLINE);
204
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800205 for (server = sgsn->ares_servers; server; server = server->next)
206 vty_out(vty, " grx-dns-add %s%s", inet_ntoa(server->addr.addr4), VTY_NEWLINE);
207
Max93408ae2016-06-28 14:10:16 +0200208 if (g_cfg->cipher != GPRS_ALGO_GEA0)
209 vty_out(vty, " encryption %s%s",
210 get_value_string(gprs_cipher_names, g_cfg->cipher),
211 VTY_NEWLINE);
Jacob Erlbeck39f040d2014-12-18 12:46:47 +0100212 if (g_cfg->gsup_server_addr.sin_addr.s_addr)
213 vty_out(vty, " gsup remote-ip %s%s",
214 inet_ntoa(g_cfg->gsup_server_addr.sin_addr), VTY_NEWLINE);
215 if (g_cfg->gsup_server_port)
216 vty_out(vty, " gsup remote-port %d%s",
217 g_cfg->gsup_server_port, VTY_NEWLINE);
Max176b62a2016-07-04 11:09:07 +0200218 vty_out(vty, " auth-policy %s%s",
219 get_value_string(sgsn_auth_pol_strs, g_cfg->auth_policy),
220 VTY_NEWLINE);
Neels Hofmeyr568a7272015-10-12 11:57:38 +0200221
222 vty_out(vty, " gsup oap-id %d%s",
223 (int)g_cfg->oap.client_id, VTY_NEWLINE);
224 if (g_cfg->oap.secret_k_present != 0)
225 vty_out(vty, " gsup oap-k %s%s",
226 osmo_hexdump_nospc(g_cfg->oap.secret_k, sizeof(g_cfg->oap.secret_k)),
227 VTY_NEWLINE);
228 if (g_cfg->oap.secret_opc_present != 0)
229 vty_out(vty, " gsup oap-opc %s%s",
230 osmo_hexdump_nospc(g_cfg->oap.secret_opc, sizeof(g_cfg->oap.secret_opc)),
231 VTY_NEWLINE);
232
Harald Welte7f6da482013-03-19 11:00:13 +0100233 llist_for_each_entry(acl, &g_cfg->imsi_acl, list)
234 vty_out(vty, " imsi-acl add %s%s", acl->imsi, VTY_NEWLINE);
235
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100236 if (llist_empty(&sgsn_apn_ctxts))
237 vty_out(vty, " ! apn * ggsn 0%s", VTY_NEWLINE);
238 llist_for_each_entry(actx, &sgsn_apn_ctxts, list) {
239 if (strlen(actx->imsi_prefix) > 0)
Holger Hans Peter Freytherb7ae0b32015-05-29 15:11:55 +0200240 vty_out(vty, " apn %s imsi-prefix %s ggsn %u%s",
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100241 actx->name, actx->imsi_prefix, actx->ggsn->id,
242 VTY_NEWLINE);
243 else
Holger Hans Peter Freytherb7ae0b32015-05-29 15:11:55 +0200244 vty_out(vty, " apn %s ggsn %u%s", actx->name,
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100245 actx->ggsn->id, VTY_NEWLINE);
246 }
247
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +0200248 if (g_cfg->cdr.filename)
249 vty_out(vty, " cdr filename %s%s", g_cfg->cdr.filename, VTY_NEWLINE);
250 else
251 vty_out(vty, " no cdr filename%s", VTY_NEWLINE);
252 vty_out(vty, " cdr interval %d%s", g_cfg->cdr.interval, VTY_NEWLINE);
253
Harald Welte94508822015-08-15 19:08:21 +0200254 vty_out(vty, " timer t3312 %d%s", g_cfg->timers.T3312, VTY_NEWLINE);
255 vty_out(vty, " timer t3322 %d%s", g_cfg->timers.T3322, VTY_NEWLINE);
256 vty_out(vty, " timer t3350 %d%s", g_cfg->timers.T3350, VTY_NEWLINE);
257 vty_out(vty, " timer t3360 %d%s", g_cfg->timers.T3360, VTY_NEWLINE);
258 vty_out(vty, " timer t3370 %d%s", g_cfg->timers.T3370, VTY_NEWLINE);
259 vty_out(vty, " timer t3313 %d%s", g_cfg->timers.T3313, VTY_NEWLINE);
260 vty_out(vty, " timer t3314 %d%s", g_cfg->timers.T3314, VTY_NEWLINE);
261 vty_out(vty, " timer t3316 %d%s", g_cfg->timers.T3316, VTY_NEWLINE);
262 vty_out(vty, " timer t3385 %d%s", g_cfg->timers.T3385, VTY_NEWLINE);
263 vty_out(vty, " timer t3386 %d%s", g_cfg->timers.T3386, VTY_NEWLINE);
264 vty_out(vty, " timer t3395 %d%s", g_cfg->timers.T3395, VTY_NEWLINE);
265 vty_out(vty, " timer t3397 %d%s", g_cfg->timers.T3397, VTY_NEWLINE);
266
Philippf1f34362016-08-26 17:00:21 +0200267 if (g_cfg->pcomp_rfc1144.active) {
268 vty_out(vty, " compression rfc1144 active slots %d%s",
269 g_cfg->pcomp_rfc1144.s01 + 1, VTY_NEWLINE);
270 } else if (g_cfg->pcomp_rfc1144.passive) {
271 vty_out(vty, " compression rfc1144 passive%s", VTY_NEWLINE);
272 } else
273 vty_out(vty, " no compression rfc1144%s", VTY_NEWLINE);
274
Philipp73f83d52016-09-02 13:38:01 +0200275 if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 1) {
276 vty_out(vty,
277 " compression v42bis active direction sgsn codewords %d strlen %d%s",
278 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
279 VTY_NEWLINE);
280 } else if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 2) {
281 vty_out(vty,
282 " compression v42bis active direction ms codewords %d strlen %d%s",
283 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
284 VTY_NEWLINE);
285 } else if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 3) {
286 vty_out(vty,
287 " compression v42bis active direction both codewords %d strlen %d%s",
288 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
289 VTY_NEWLINE);
290 } else if (g_cfg->dcomp_v42bis.passive) {
291 vty_out(vty, " compression v42bis passive%s", VTY_NEWLINE);
292 } else
293 vty_out(vty, " no compression v42bis%s", VTY_NEWLINE);
294
Neels Hofmeyr2188a772016-05-20 21:59:55 +0200295#ifdef BUILD_IU
Neels Hofmeyra7a39472017-07-05 15:19:52 +0200296 ranap_iu_vty_config_write(vty, " ");
Neels Hofmeyr2188a772016-05-20 21:59:55 +0200297#endif
298
Harald Welte288be162010-05-01 16:48:27 +0200299 return CMD_SUCCESS;
300}
301
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100302#define SGSN_STR "Configure the SGSN\n"
303#define GGSN_STR "Configure the GGSN information\n"
Harald Weltee300d002010-06-02 12:41:34 +0200304
305DEFUN(cfg_sgsn, cfg_sgsn_cmd,
306 "sgsn",
307 SGSN_STR)
Harald Welte288be162010-05-01 16:48:27 +0200308{
309 vty->node = SGSN_NODE;
310 return CMD_SUCCESS;
311}
312
Harald Weltee300d002010-06-02 12:41:34 +0200313DEFUN(cfg_sgsn_bind_addr, cfg_sgsn_bind_addr_cmd,
314 "gtp local-ip A.B.C.D",
315 "GTP Parameters\n"
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100316 "Set the IP address for the local GTP bind\n"
317 "IPv4 Address\n")
Harald Weltee300d002010-06-02 12:41:34 +0200318{
319 inet_aton(argv[0], &g_cfg->gtp_listenaddr.sin_addr);
320
321 return CMD_SUCCESS;
322}
323
Harald Welted193cb32010-05-17 22:58:03 +0200324DEFUN(cfg_ggsn_remote_ip, cfg_ggsn_remote_ip_cmd,
325 "ggsn <0-255> remote-ip A.B.C.D",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100326 GGSN_STR "GGSN Number\n" IP_STR "IPv4 Address\n")
Harald Welted193cb32010-05-17 22:58:03 +0200327{
328 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200329 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welte288be162010-05-01 16:48:27 +0200330
Harald Welted193cb32010-05-17 22:58:03 +0200331 inet_aton(argv[1], &ggc->remote_addr);
Harald Welte288be162010-05-01 16:48:27 +0200332
Harald Welted193cb32010-05-17 22:58:03 +0200333 return CMD_SUCCESS;
334}
335
336#if 0
337DEFUN(cfg_ggsn_remote_port, cfg_ggsn_remote_port_cmd,
338 "ggsn <0-255> remote-port <0-65535>",
339 "")
340{
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 uint16_t port = atoi(argv[1]);
344
345}
346#endif
347
348DEFUN(cfg_ggsn_gtp_version, cfg_ggsn_gtp_version_cmd,
349 "ggsn <0-255> gtp-version (0|1)",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100350 GGSN_STR "GGSN Number\n" "GTP Version\n"
351 "Version 0\n" "Version 1\n")
Harald Welted193cb32010-05-17 22:58:03 +0200352{
353 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200354 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welted193cb32010-05-17 22:58:03 +0200355
356 if (atoi(argv[1]))
357 ggc->gtp_version = 1;
358 else
359 ggc->gtp_version = 0;
360
361 return CMD_SUCCESS;
362}
363
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800364DEFUN(cfg_ggsn_dynamic_lookup, cfg_ggsn_dynamic_lookup_cmd,
365 "ggsn dynamic",
366 GGSN_STR "Enable dynamic GRX based look-up (requires restart)\n")
367{
368 sgsn->cfg.dynamic_lookup = 1;
369 return CMD_SUCCESS;
370}
371
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800372DEFUN(cfg_grx_ggsn, cfg_grx_ggsn_cmd,
373 "grx-dns-add A.B.C.D",
374 "Add DNS server\nIPv4 address\n")
375{
376 struct ares_addr_node *node = talloc_zero(tall_bsc_ctx, struct ares_addr_node);
377 node->family = AF_INET;
378 inet_aton(argv[0], &node->addr.addr4);
379
380 node->next = sgsn->ares_servers;
381 sgsn->ares_servers = node;
382 return CMD_SUCCESS;
383}
384
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100385#define APN_STR "Configure the information per APN\n"
386#define APN_GW_STR "The APN gateway name optionally prefixed by '*' (wildcard)\n"
387
388static int add_apn_ggsn_mapping(struct vty *vty, const char *apn_str,
389 const char *imsi_prefix, int ggsn_id)
390{
391 struct apn_ctx *actx;
392 struct sgsn_ggsn_ctx *ggsn;
393
394 ggsn = sgsn_ggsn_ctx_by_id(ggsn_id);
395 if (ggsn == NULL) {
396 vty_out(vty, "%% a GGSN with id %d has not been defined%s",
397 ggsn_id, VTY_NEWLINE);
398 return CMD_WARNING;
399 }
400
401 actx = sgsn_apn_ctx_find_alloc(apn_str, imsi_prefix);
402 if (!actx) {
403 vty_out(vty, "%% unable to create APN context for %s/%s%s",
404 apn_str, imsi_prefix, VTY_NEWLINE);
405 return CMD_WARNING;
406 }
407
408 actx->ggsn = ggsn;
409
410 return CMD_SUCCESS;
411}
412
Harald Welted193cb32010-05-17 22:58:03 +0200413DEFUN(cfg_apn_ggsn, cfg_apn_ggsn_cmd,
414 "apn APNAME ggsn <0-255>",
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100415 APN_STR APN_GW_STR
416 "Select the GGSN to use when the APN gateway prefix matches\n"
417 "The GGSN id")
Harald Welted193cb32010-05-17 22:58:03 +0200418{
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100419
420 return add_apn_ggsn_mapping(vty, argv[0], "", atoi(argv[1]));
Harald Welted193cb32010-05-17 22:58:03 +0200421}
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100422
423DEFUN(cfg_apn_imsi_ggsn, cfg_apn_imsi_ggsn_cmd,
424 "apn APNAME imsi-prefix IMSIPRE ggsn <0-255>",
425 APN_STR APN_GW_STR
426 "Restrict rule to a certain IMSI prefix\n"
427 "An IMSI prefix\n"
428 "Select the GGSN to use when APN gateway and IMSI prefix match\n"
429 "The GGSN id")
430{
431
432 return add_apn_ggsn_mapping(vty, argv[0], argv[1], atoi(argv[2]));
433}
Harald Welted193cb32010-05-17 22:58:03 +0200434
435const struct value_string gprs_mm_st_strs[] = {
436 { GMM_DEREGISTERED, "DEREGISTERED" },
437 { GMM_COMMON_PROC_INIT, "COMMON PROCEDURE (INIT)" },
438 { GMM_REGISTERED_NORMAL, "REGISTERED (NORMAL)" },
Harald Weltebffeff82010-06-09 15:50:45 +0200439 { GMM_REGISTERED_SUSPENDED, "REGISTERED (SUSPENDED)" },
Harald Welted193cb32010-05-17 22:58:03 +0200440 { GMM_DEREGISTERED_INIT, "DEREGISTERED (INIT)" },
441 { 0, NULL }
442};
443
Harald Welte471ac7d2016-12-15 19:48:58 +0100444static char *gtp_ntoa(struct ul16_t *ul)
445{
446 if (ul->l == 4) {
447 struct in_addr *ia = (struct in_addr *) ul;
448 return inet_ntoa(*ia);
449 } else {
450 return "UNKNOWN";
451 }
452}
453
Harald Welted193cb32010-05-17 22:58:03 +0200454static void vty_dump_pdp(struct vty *vty, const char *pfx,
455 struct sgsn_pdp_ctx *pdp)
456{
Jacob Erlbeck99985b52014-10-13 10:32:00 +0200457 const char *imsi = pdp->mm ? pdp->mm->imsi : "(detaching)";
Harald Welte471ac7d2016-12-15 19:48:58 +0100458 vty_out(vty, "%sPDP Context IMSI: %s, SAPI: %u, NSAPI: %u, TI: %u%s",
459 pfx, imsi, pdp->sapi, pdp->nsapi, pdp->ti, VTY_NEWLINE);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200460 if (pdp->lib) {
461 vty_out(vty, "%s APN: %s%s", pfx,
462 gprs_apn2str(pdp->lib->apn_use.v, pdp->lib->apn_use.l),
463 VTY_NEWLINE);
464 vty_out(vty, "%s PDP Address: %s%s", pfx,
465 gprs_pdpaddr2str(pdp->lib->eua.v, pdp->lib->eua.l),
466 VTY_NEWLINE);
467 vty_out(vty, "%s GTP Local Control(%s / TEIC: 0x%08x) ", pfx,
468 gtp_ntoa(&pdp->lib->gsnlc), pdp->lib->teic_own);
469 vty_out(vty, "Data(%s / TEID: 0x%08x)%s",
470 gtp_ntoa(&pdp->lib->gsnlu), pdp->lib->teid_own, VTY_NEWLINE);
471 vty_out(vty, "%s GTP Remote Control(%s / TEIC: 0x%08x) ", pfx,
472 gtp_ntoa(&pdp->lib->gsnrc), pdp->lib->teic_gn);
473 vty_out(vty, "Data(%s / TEID: 0x%08x)%s",
474 gtp_ntoa(&pdp->lib->gsnru), pdp->lib->teid_gn, VTY_NEWLINE);
475 }
Harald Welte471ac7d2016-12-15 19:48:58 +0100476
Harald Welteefbdee92010-06-10 00:20:12 +0200477 vty_out_rate_ctr_group(vty, " ", pdp->ctrg);
Harald Welted193cb32010-05-17 22:58:03 +0200478}
479
480static void vty_dump_mmctx(struct vty *vty, const char *pfx,
481 struct sgsn_mm_ctx *mm, int pdp)
482{
483 vty_out(vty, "%sMM Context for IMSI %s, IMEI %s, P-TMSI %08x%s",
484 pfx, mm->imsi, mm->imei, mm->p_tmsi, VTY_NEWLINE);
Holger Hans Peter Freyther8ee13e22015-05-18 10:00:03 +0200485 vty_out(vty, "%s MSISDN: %s, TLLI: %08x%s HLR: %s",
Harald Weltef97ee042015-12-25 19:12:21 +0100486 pfx, mm->msisdn, mm->gb.tlli, mm->hlr, VTY_NEWLINE);
Harald Welted193cb32010-05-17 22:58:03 +0200487 vty_out(vty, "%s MM State: %s, Routeing Area: %u-%u-%u-%u, "
488 "Cell ID: %u%s", pfx,
Alexander Couzens4f8da6d2017-01-31 15:34:26 +0100489 get_value_string(gprs_mm_st_strs, mm->gmm_state),
Harald Welted193cb32010-05-17 22:58:03 +0200490 mm->ra.mcc, mm->ra.mnc, mm->ra.lac, mm->ra.rac,
Harald Weltef97ee042015-12-25 19:12:21 +0100491 mm->gb.cell_id, VTY_NEWLINE);
Harald Welted193cb32010-05-17 22:58:03 +0200492
Harald Welte8acd88f2010-05-18 10:57:45 +0200493 vty_out_rate_ctr_group(vty, " ", mm->ctrg);
494
Harald Welted193cb32010-05-17 22:58:03 +0200495 if (pdp) {
496 struct sgsn_pdp_ctx *pdp;
497
498 llist_for_each_entry(pdp, &mm->pdp_list, list)
499 vty_dump_pdp(vty, " ", pdp);
500 }
501}
502
503DEFUN(show_sgsn, show_sgsn_cmd, "show sgsn",
504 SHOW_STR "Display information about the SGSN")
505{
Jacob Erlbeck80547992014-12-19 19:19:46 +0100506 if (sgsn->gsup_client) {
507 struct ipa_client_conn *link = sgsn->gsup_client->link;
508 vty_out(vty,
509 " Remote authorization: %sconnected to %s:%d via GSUP%s",
510 sgsn->gsup_client->is_connected ? "" : "not ",
511 link->addr, link->port,
512 VTY_NEWLINE);
513 }
Harald Welted193cb32010-05-17 22:58:03 +0200514 /* FIXME: statistics */
515 return CMD_SUCCESS;
516}
517
518#define MMCTX_STR "MM Context\n"
519#define INCLUDE_PDP_STR "Include PDP Context Information\n"
520
521#if 0
522DEFUN(show_mmctx_tlli, show_mmctx_tlli_cmd,
523 "show mm-context tlli HEX [pdp]",
524 SHOW_STR MMCTX_STR "Identify by TLLI\n" "TLLI\n" INCLUDE_PDP_STR)
525{
526 uint32_t tlli;
527 struct sgsn_mm_ctx *mm;
528
529 tlli = strtoul(argv[0], NULL, 16);
530 mm = sgsn_mm_ctx_by_tlli(tlli);
531 if (!mm) {
532 vty_out(vty, "No MM context for TLLI %08x%s",
533 tlli, VTY_NEWLINE);
534 return CMD_WARNING;
535 }
536 vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
537 return CMD_SUCCESS;
538}
539#endif
540
541DEFUN(swow_mmctx_imsi, show_mmctx_imsi_cmd,
542 "show mm-context imsi IMSI [pdp]",
543 SHOW_STR MMCTX_STR "Identify by IMSI\n" "IMSI of the MM Context\n"
544 INCLUDE_PDP_STR)
545{
546 struct sgsn_mm_ctx *mm;
547
548 mm = sgsn_mm_ctx_by_imsi(argv[0]);
549 if (!mm) {
550 vty_out(vty, "No MM context for IMSI %s%s",
551 argv[0], VTY_NEWLINE);
552 return CMD_WARNING;
553 }
554 vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
555 return CMD_SUCCESS;
556}
557
558DEFUN(swow_mmctx_all, show_mmctx_all_cmd,
559 "show mm-context all [pdp]",
560 SHOW_STR MMCTX_STR "All MM Contexts\n" INCLUDE_PDP_STR)
561{
562 struct sgsn_mm_ctx *mm;
563
564 llist_for_each_entry(mm, &sgsn_mm_ctxts, list)
565 vty_dump_mmctx(vty, "", mm, argv[0] ? 1 : 0);
566
567 return CMD_SUCCESS;
568}
569
Harald Welted193cb32010-05-17 22:58:03 +0200570DEFUN(show_pdpctx_all, show_pdpctx_all_cmd,
571 "show pdp-context all",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100572 SHOW_STR "Display information on PDP Context\n" "Show everything\n")
Harald Welted193cb32010-05-17 22:58:03 +0200573{
574 struct sgsn_pdp_ctx *pdp;
575
576 llist_for_each_entry(pdp, &sgsn_pdp_ctxts, g_list)
577 vty_dump_pdp(vty, "", pdp);
578
579 return CMD_SUCCESS;
580}
Harald Welte288be162010-05-01 16:48:27 +0200581
Harald Welte7f6da482013-03-19 11:00:13 +0100582
583DEFUN(imsi_acl, cfg_imsi_acl_cmd,
584 "imsi-acl (add|del) IMSI",
585 "Access Control List of foreign IMSIs\n"
586 "Add IMSI to ACL\n"
587 "Remove IMSI from ACL\n"
588 "IMSI of subscriber\n")
589{
Philipp Maier6ee49d82017-02-28 16:53:07 +0100590 char imsi_sanitized[GSM23003_IMSI_MAX_DIGITS+1];
Harald Welte7f6da482013-03-19 11:00:13 +0100591 const char *op = argv[0];
Philipp Maier6ee49d82017-02-28 16:53:07 +0100592 const char *imsi = imsi_sanitized;
Harald Welte7f6da482013-03-19 11:00:13 +0100593 int rc;
594
Philipp Maier6ee49d82017-02-28 16:53:07 +0100595 /* Sanitize IMSI */
596 if (strlen(argv[1]) > GSM23003_IMSI_MAX_DIGITS) {
597 vty_out(vty, "%% IMSI (%s) too long -- ignored!%s",
598 argv[1], VTY_NEWLINE);
599 return CMD_WARNING;
600 }
601 memset(imsi_sanitized, '0', sizeof(imsi_sanitized));
602 strcpy(imsi_sanitized+GSM23003_IMSI_MAX_DIGITS-strlen(argv[1]),argv[1]);
603
Harald Welte7f6da482013-03-19 11:00:13 +0100604 if (!strcmp(op, "add"))
Jacob Erlbeck3b5d4072014-10-24 15:11:03 +0200605 rc = sgsn_acl_add(imsi, g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +0100606 else
Jacob Erlbeck3b5d4072014-10-24 15:11:03 +0200607 rc = sgsn_acl_del(imsi, g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +0100608
609 if (rc < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100610 vty_out(vty, "%% unable to %s ACL%s", op, VTY_NEWLINE);
Harald Welte7f6da482013-03-19 11:00:13 +0100611 return CMD_WARNING;
612 }
613
614 return CMD_SUCCESS;
615}
616
Max93408ae2016-06-28 14:10:16 +0200617DEFUN(cfg_encrypt, cfg_encrypt_cmd,
618 "encryption (GEA0|GEA1|GEA2|GEA3|GEA4)",
619 "Set encryption algorithm for SGSN\n"
620 "Use GEA0 (no encryption)\n"
621 "Use GEA1\nUse GEA2\nUse GEA3\nUse GEA4\n")
622{
Max93408ae2016-06-28 14:10:16 +0200623 enum gprs_ciph_algo c = get_string_value(gprs_cipher_names, argv[0]);
Max086067f2017-05-02 13:03:28 +0200624 if (c != GPRS_ALGO_GEA0) {
625 if (!gprs_cipher_supported(c)) {
626 vty_out(vty, "%% cipher %s is unsupported in current version%s", argv[0], VTY_NEWLINE);
627 return CMD_WARNING;
628 }
629
630 if (!g_cfg->require_authentication) {
631 vty_out(vty, "%% unable to use encryption %s without authentication: please adjust auth-policy%s",
632 argv[0], VTY_NEWLINE);
633 return CMD_WARNING;
634 }
Max93408ae2016-06-28 14:10:16 +0200635 }
636
637 g_cfg->cipher = c;
638
639 return CMD_SUCCESS;
640}
641
Harald Welte3dfb5492013-03-19 11:48:54 +0100642DEFUN(cfg_auth_policy, cfg_auth_policy_cmd,
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100643 "auth-policy (accept-all|closed|acl-only|remote)",
Harald Welte3dfb5492013-03-19 11:48:54 +0100644 "Autorization Policy of SGSN\n"
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100645 "Accept all IMSIs (DANGEROUS)\n"
646 "Accept only home network subscribers or those in the ACL\n"
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100647 "Accept only subscribers in the ACL\n"
648 "Use remote subscription data only (HLR)\n")
Harald Welte3dfb5492013-03-19 11:48:54 +0100649{
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100650 int val = get_string_value(sgsn_auth_pol_strs, argv[0]);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100651 OSMO_ASSERT(val >= SGSN_AUTH_POLICY_OPEN && val <= SGSN_AUTH_POLICY_REMOTE);
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100652 g_cfg->auth_policy = val;
Jacob Erlbeck9d4f46c2014-12-17 13:20:08 +0100653 g_cfg->require_authentication = (val == SGSN_AUTH_POLICY_REMOTE);
Jacob Erlbeck771573c2014-12-19 18:08:48 +0100654 g_cfg->require_update_location = (val == SGSN_AUTH_POLICY_REMOTE);
Harald Welte3dfb5492013-03-19 11:48:54 +0100655
656 return CMD_SUCCESS;
657}
658
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100659/* Subscriber */
Neels Hofmeyr396f2e62017-09-04 15:13:25 +0200660#include <osmocom/sgsn/gprs_subscriber.h>
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100661
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100662static void subscr_dump_full_vty(struct vty *vty, struct gprs_subscr *gsub, int pending)
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100663{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100664#if 0
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100665 char expire_time[200];
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100666#endif
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100667 struct gsm_auth_tuple *at;
668 int at_idx;
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100669 struct sgsn_subscriber_pdp_data *pdp;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100670
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100671 vty_out(vty, " Authorized: %d%s",
672 gsub->authorized, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100673 vty_out(vty, " LAC: %d/0x%x%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100674 gsub->lac, gsub->lac, VTY_NEWLINE);
675 vty_out(vty, " IMSI: %s%s", gsub->imsi, VTY_NEWLINE);
676 if (gsub->tmsi != GSM_RESERVED_TMSI)
677 vty_out(vty, " TMSI: %08X%s", gsub->tmsi,
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100678 VTY_NEWLINE);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100679 if (gsub->sgsn_data->msisdn_len > 0)
Holger Hans Peter Freytherf7b38262015-04-23 16:58:33 -0400680 vty_out(vty, " MSISDN (BCD): %s%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100681 osmo_hexdump(gsub->sgsn_data->msisdn,
682 gsub->sgsn_data->msisdn_len),
Holger Hans Peter Freytherf7b38262015-04-23 16:58:33 -0400683 VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100684
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100685 if (strlen(gsub->imei) > 0)
686 vty_out(vty, " IMEI: %s%s", gsub->imei, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100687
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100688 for (at_idx = 0; at_idx < ARRAY_SIZE(gsub->sgsn_data->auth_triplets);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100689 at_idx++) {
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100690 at = &gsub->sgsn_data->auth_triplets[at_idx];
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100691 if (at->key_seq == GSM_KEY_SEQ_INVAL)
692 continue;
693
694 vty_out(vty, " A3A8 tuple (used %d times): ",
695 at->use_count);
Harald Welte89837d42016-05-06 23:28:11 +0200696 vty_out(vty, " CKSN: %d, ",
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100697 at->key_seq);
Harald Welte89837d42016-05-06 23:28:11 +0200698 if (at->vec.auth_types & OSMO_AUTH_TYPE_GSM) {
699 vty_out(vty, "RAND: %s, ",
700 osmo_hexdump(at->vec.rand,
701 sizeof(at->vec.rand)));
702 vty_out(vty, "SRES: %s, ",
703 osmo_hexdump(at->vec.sres,
704 sizeof(at->vec.sres)));
705 vty_out(vty, "Kc: %s%s",
706 osmo_hexdump(at->vec.kc,
707 sizeof(at->vec.kc)), VTY_NEWLINE);
708 }
709 if (at->vec.auth_types & OSMO_AUTH_TYPE_UMTS) {
710 vty_out(vty, " AUTN: %s, ",
711 osmo_hexdump(at->vec.autn,
712 sizeof(at->vec.autn)));
713 vty_out(vty, "RES: %s, ",
714 osmo_hexdump(at->vec.res, at->vec.res_len));
715 vty_out(vty, "IK: %s, ",
716 osmo_hexdump(at->vec.ik, sizeof(at->vec.ik)));
717 vty_out(vty, "CK: %s, ",
718 osmo_hexdump(at->vec.ck, sizeof(at->vec.ck)));
719 }
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100720 }
721
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100722 llist_for_each_entry(pdp, &gsub->sgsn_data->pdp_list, list) {
Holger Hans Peter Freytherd05e0692015-04-23 16:59:04 -0400723 vty_out(vty, " PDP info: Id: %d, Type: 0x%04x, APN: '%s' QoS: %s%s",
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100724 pdp->context_id, pdp->pdp_type, pdp->apn_str,
Holger Hans Peter Freytherd05e0692015-04-23 16:59:04 -0400725 osmo_hexdump(pdp->qos_subscribed, pdp->qos_subscribed_len),
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100726 VTY_NEWLINE);
727 }
728
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100729#if 0
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100730 /* print the expiration time of a subscriber */
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100731 if (gsub->expire_lu) {
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100732 strftime(expire_time, sizeof(expire_time),
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100733 "%a, %d %b %Y %T %z", localtime(&gsub->expire_lu));
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100734 expire_time[sizeof(expire_time) - 1] = '\0';
735 vty_out(vty, " Expiration Time: %s%s", expire_time, VTY_NEWLINE);
736 }
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100737#endif
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100738
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100739 if (gsub->flags)
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100740 vty_out(vty, " Flags: %s%s%s%s%s%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100741 gsub->flags & GPRS_SUBSCRIBER_FIRST_CONTACT ?
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100742 "FIRST_CONTACT " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100743 gsub->flags & GPRS_SUBSCRIBER_CANCELLED ?
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100744 "CANCELLED " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100745 gsub->flags & GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING ?
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100746 "UPDATE_LOCATION_PENDING " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100747 gsub->flags & GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING ?
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100748 "AUTH_INFO_PENDING " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100749 gsub->flags & GPRS_SUBSCRIBER_ENABLE_PURGE ?
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100750 "ENABLE_PURGE " : "",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100751 VTY_NEWLINE);
752
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100753 vty_out(vty, " Use count: %u%s", gsub->use_count, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100754}
755
756DEFUN(show_subscr_cache,
757 show_subscr_cache_cmd,
758 "show subscriber cache",
759 SHOW_STR "Show information about subscribers\n"
760 "Display contents of subscriber cache\n")
761{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100762 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100763
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100764 llist_for_each_entry(subscr, gprs_subscribers, entry) {
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100765 vty_out(vty, " Subscriber:%s", VTY_NEWLINE);
766 subscr_dump_full_vty(vty, subscr, 0);
767 }
768
769 return CMD_SUCCESS;
770}
771
772#define UPDATE_SUBSCR_STR "update-subscriber imsi IMSI "
773#define UPDATE_SUBSCR_HELP "Update subscriber list\n" \
774 "Use the IMSI to select the subscriber\n" \
775 "The IMSI\n"
776
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100777#define UPDATE_SUBSCR_INSERT_HELP "Insert data into the subscriber record\n"
778
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100779DEFUN(update_subscr_insert_auth_triplet, update_subscr_insert_auth_triplet_cmd,
780 UPDATE_SUBSCR_STR "insert auth-triplet <1-5> sres SRES rand RAND kc KC",
781 UPDATE_SUBSCR_HELP
782 UPDATE_SUBSCR_INSERT_HELP
783 "Update authentication triplet\n"
784 "Triplet index\n"
785 "Set SRES value\nSRES value (4 byte) in hex\n"
786 "Set RAND value\nRAND value (16 byte) in hex\n"
787 "Set Kc value\nKc value (8 byte) in hex\n")
788{
789 const char *imsi = argv[0];
790 const int cksn = atoi(argv[1]) - 1;
791 const char *sres_str = argv[2];
792 const char *rand_str = argv[3];
793 const char *kc_str = argv[4];
794 struct gsm_auth_tuple at = {0,};
795
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100796 struct gprs_subscr *subscr;
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100797
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100798 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100799 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100800 vty_out(vty, "%% unable get subscriber record for %s%s",
801 imsi, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100802 return CMD_WARNING;
803 }
804
805 OSMO_ASSERT(subscr->sgsn_data);
806
Harald Welte121e9a42016-04-20 13:13:19 +0200807 if (osmo_hexparse(sres_str, &at.vec.sres[0], sizeof(at.vec.sres)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100808 vty_out(vty, "%% invalid SRES value '%s'%s",
809 sres_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100810 goto failed;
811 }
Harald Welte121e9a42016-04-20 13:13:19 +0200812 if (osmo_hexparse(rand_str, &at.vec.rand[0], sizeof(at.vec.rand)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100813 vty_out(vty, "%% invalid RAND value '%s'%s",
814 rand_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100815 goto failed;
816 }
Harald Welte121e9a42016-04-20 13:13:19 +0200817 if (osmo_hexparse(kc_str, &at.vec.kc[0], sizeof(at.vec.kc)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100818 vty_out(vty, "%% invalid Kc value '%s'%s",
819 kc_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100820 goto failed;
821 }
822 at.key_seq = cksn;
823
824 subscr->sgsn_data->auth_triplets[cksn] = at;
825 subscr->sgsn_data->auth_triplets_updated = 1;
826
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100827 gprs_subscr_put(subscr);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100828
829 return CMD_SUCCESS;
830
831failed:
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100832 gprs_subscr_put(subscr);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100833 return CMD_SUCCESS;
834}
835
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100836DEFUN(update_subscr_cancel, update_subscr_cancel_cmd,
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100837 UPDATE_SUBSCR_STR "cancel (update-procedure|subscription-withdraw)",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100838 UPDATE_SUBSCR_HELP
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100839 "Cancel (remove) subscriber record\n"
840 "The MS moved to another SGSN\n"
841 "The subscription is no longer valid\n")
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100842{
843 const char *imsi = argv[0];
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100844 const char *cancel_type = argv[1];
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100845
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100846 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100847
848 subscr = gprs_subscr_get_by_imsi(imsi);
849 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100850 vty_out(vty, "%% no subscriber record for %s%s",
851 imsi, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100852 return CMD_WARNING;
853 }
854
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100855 if (strcmp(cancel_type, "update-procedure") == 0)
856 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
857 else
858 subscr->sgsn_data->error_cause = GMM_CAUSE_IMPL_DETACHED;
859
Jacob Erlbeck37139e52015-01-23 13:52:55 +0100860 gprs_subscr_cancel(subscr);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100861 gprs_subscr_put(subscr);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100862
863 return CMD_SUCCESS;
864}
865
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100866DEFUN(update_subscr_create, update_subscr_create_cmd,
867 UPDATE_SUBSCR_STR "create",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100868 UPDATE_SUBSCR_HELP
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100869 "Create a subscriber entry\n")
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100870{
871 const char *imsi = argv[0];
872
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100873 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100874
875 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100876 if (subscr) {
877 vty_out(vty, "%% subscriber record already exists for %s%s",
878 imsi, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100879 return CMD_WARNING;
880 }
881
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100882 subscr = gprs_subscr_get_or_create(imsi);
883 subscr->keep_in_ram = 1;
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100884 gprs_subscr_put(subscr);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100885
886 return CMD_SUCCESS;
887}
888
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100889DEFUN(update_subscr_destroy, update_subscr_destroy_cmd,
890 UPDATE_SUBSCR_STR "destroy",
891 UPDATE_SUBSCR_HELP
892 "Destroy a subscriber entry\n")
893{
894 const char *imsi = argv[0];
895
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100896 struct gprs_subscr *subscr;
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100897
898 subscr = gprs_subscr_get_by_imsi(imsi);
899 if (!subscr) {
900 vty_out(vty, "%% subscriber record does not exist for %s%s",
901 imsi, VTY_NEWLINE);
902 return CMD_WARNING;
903 }
904
905 subscr->keep_in_ram = 0;
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100906 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100907 gprs_subscr_cancel(subscr);
908 if (subscr->use_count > 1)
909 vty_out(vty, "%% subscriber is still in use%s",
910 VTY_NEWLINE);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100911 gprs_subscr_put(subscr);
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100912
913 return CMD_SUCCESS;
914}
915
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100916#define UL_ERR_STR "system-failure|data-missing|unexpected-data-value|" \
917 "unknown-subscriber|roaming-not-allowed"
918
919#define UL_ERR_HELP \
920 "Force error code SystemFailure\n" \
921 "Force error code DataMissing\n" \
922 "Force error code UnexpectedDataValue\n" \
923 "Force error code UnknownSubscriber\n" \
924 "Force error code RoamingNotAllowed\n"
925
926DEFUN(update_subscr_update_location_result, update_subscr_update_location_result_cmd,
927 UPDATE_SUBSCR_STR "update-location-result (ok|" UL_ERR_STR ")",
928 UPDATE_SUBSCR_HELP
929 "Complete the update location procedure\n"
930 "The update location request succeeded\n"
931 UL_ERR_HELP)
932{
933 const char *imsi = argv[0];
934 const char *ret_code_str = argv[1];
935
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100936 struct gprs_subscr *subscr;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100937
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100938 const struct value_string cause_mapping[] = {
939 { GMM_CAUSE_NET_FAIL, "system-failure" },
940 { GMM_CAUSE_INV_MAND_INFO, "data-missing" },
941 { GMM_CAUSE_PROTO_ERR_UNSPEC, "unexpected-data-value" },
942 { GMM_CAUSE_IMSI_UNKNOWN, "unknown-subscriber" },
943 { GMM_CAUSE_GPRS_NOTALLOWED, "roaming-not-allowed" },
944 { 0, NULL }
945 };
946
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100947 subscr = gprs_subscr_get_by_imsi(imsi);
948 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100949 vty_out(vty, "%% unable to get subscriber record for %s%s",
950 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100951 return CMD_WARNING;
952 }
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100953
954 if (strcmp(ret_code_str, "ok") == 0) {
955 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100956 subscr->authorized = 1;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100957 } else {
958 subscr->sgsn_data->error_cause =
959 get_string_value(cause_mapping, ret_code_str);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100960 subscr->authorized = 0;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100961 }
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100962
963 gprs_subscr_update(subscr);
964
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100965 gprs_subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100966
967 return CMD_SUCCESS;
968}
969
970DEFUN(update_subscr_update_auth_info, update_subscr_update_auth_info_cmd,
971 UPDATE_SUBSCR_STR "update-auth-info",
972 UPDATE_SUBSCR_HELP
973 "Complete the send authentication info procedure\n")
974{
975 const char *imsi = argv[0];
976
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100977 struct gprs_subscr *subscr;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100978
979 subscr = gprs_subscr_get_by_imsi(imsi);
980 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100981 vty_out(vty, "%% unable to get subscriber record for %s%s",
982 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100983 return CMD_WARNING;
984 }
985
986 gprs_subscr_update_auth_info(subscr);
987
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100988 gprs_subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100989
990 return CMD_SUCCESS;
991}
992
Jacob Erlbeck39f040d2014-12-18 12:46:47 +0100993DEFUN(cfg_gsup_remote_ip, cfg_gsup_remote_ip_cmd,
994 "gsup remote-ip A.B.C.D",
995 "GSUP Parameters\n"
996 "Set the IP address of the remote GSUP server\n"
997 "IPv4 Address\n")
998{
999 inet_aton(argv[0], &g_cfg->gsup_server_addr.sin_addr);
1000
1001 return CMD_SUCCESS;
1002}
1003
1004DEFUN(cfg_gsup_remote_port, cfg_gsup_remote_port_cmd,
1005 "gsup remote-port <0-65535>",
1006 "GSUP Parameters\n"
1007 "Set the TCP port of the remote GSUP server\n"
1008 "Remote TCP port\n")
1009{
1010 g_cfg->gsup_server_port = atoi(argv[0]);
1011
1012 return CMD_SUCCESS;
1013}
1014
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001015DEFUN(cfg_gsup_oap_id, cfg_gsup_oap_id_cmd,
1016 "gsup oap-id <0-65535>",
1017 "GSUP Parameters\n"
1018 "Set the SGSN's OAP client ID\nOAP client ID (0 == disabled)\n")
1019{
1020 /* VTY ensures range */
1021 g_cfg->oap.client_id = (uint16_t)atoi(argv[0]);
1022 return CMD_SUCCESS;
1023}
1024
1025DEFUN(cfg_gsup_oap_k, cfg_gsup_oap_k_cmd,
1026 "gsup oap-k K",
1027 "GSUP Parameters\n"
1028 "Set the OAP shared secret K\nK value (16 byte) hex\n")
1029{
1030 const char *k = argv[0];
1031
1032 g_cfg->oap.secret_k_present = 0;
1033
1034 if ((!k) || (strlen(k) == 0))
1035 goto disable;
1036
1037 int k_len = osmo_hexparse(k,
1038 g_cfg->oap.secret_k,
1039 sizeof(g_cfg->oap.secret_k));
1040 if (k_len != 16) {
1041 vty_out(vty, "%% need exactly 16 octets for oap-k, got %d.%s",
1042 k_len, VTY_NEWLINE);
1043 goto disable;
1044 }
1045
1046 g_cfg->oap.secret_k_present = 1;
1047 return CMD_SUCCESS;
1048
1049disable:
1050 if (g_cfg->oap.client_id > 0) {
1051 vty_out(vty, "%% OAP client ID set, but invalid oap-k value disables OAP.%s",
1052 VTY_NEWLINE);
1053 return CMD_WARNING;
1054 }
1055 return CMD_SUCCESS;
1056}
1057
1058DEFUN(cfg_gsup_oap_opc, cfg_gsup_oap_opc_cmd,
1059 "gsup oap-opc OPC",
1060 "GSUP Parameters\n"
1061 "Set the OAP shared secret OPC\nOPC value (16 byte) hex\n")
1062{
1063 const char *opc = argv[0];
1064
1065 g_cfg->oap.secret_opc_present = 0;
1066
1067 if ((!opc) || (strlen(opc) == 0))
1068 goto disable;
1069
1070 int opc_len = osmo_hexparse(opc,
1071 g_cfg->oap.secret_opc,
1072 sizeof(g_cfg->oap.secret_opc));
1073 if (opc_len != 16) {
1074 vty_out(vty, "%% need exactly 16 octets for oap-opc, got %d.%s",
1075 opc_len, VTY_NEWLINE);
1076 goto disable;
1077 }
1078
1079 g_cfg->oap.secret_opc_present = 1;
1080 return CMD_SUCCESS;
1081
1082disable:
1083 if (g_cfg->oap.client_id > 0) {
1084 vty_out(vty, "%% OAP client ID set, but invalid oap-opc value disables OAP.%s",
1085 VTY_NEWLINE);
1086 return CMD_WARNING;
1087 }
1088 return CMD_SUCCESS;
1089}
1090
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001091DEFUN(cfg_apn_name, cfg_apn_name_cmd,
1092 "access-point-name NAME",
1093 "Configure a global list of allowed APNs\n"
1094 "Add this NAME to the list\n")
1095{
1096 return add_apn_ggsn_mapping(vty, argv[0], "", 0);
1097}
1098
1099DEFUN(cfg_no_apn_name, cfg_no_apn_name_cmd,
1100 "no access-point-name NAME",
1101 NO_STR "Configure a global list of allowed APNs\n"
1102 "Remove entry with NAME\n")
1103{
1104 struct apn_ctx *apn_ctx = sgsn_apn_ctx_by_name(argv[0], "");
1105 if (!apn_ctx)
1106 return CMD_SUCCESS;
1107
1108 sgsn_apn_ctx_free(apn_ctx);
1109 return CMD_SUCCESS;
1110}
1111
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001112DEFUN(cfg_cdr_filename, cfg_cdr_filename_cmd,
1113 "cdr filename NAME",
1114 "CDR\nSet filename\nname\n")
1115{
1116 talloc_free(g_cfg->cdr.filename);
1117 g_cfg->cdr.filename = talloc_strdup(tall_vty_ctx, argv[0]);
1118 return CMD_SUCCESS;
1119}
1120
1121DEFUN(cfg_no_cdr_filename, cfg_no_cdr_filename_cmd,
1122 "no cdr filename",
1123 NO_STR "CDR\nDisable CDR generation\n")
1124{
1125 talloc_free(g_cfg->cdr.filename);
1126 g_cfg->cdr.filename = NULL;
1127 return CMD_SUCCESS;
1128}
1129
1130DEFUN(cfg_cdr_interval, cfg_cdr_interval_cmd,
1131 "cdr interval <1-2147483647>",
1132 "CDR\nPDP periodic log interval\nSeconds\n")
1133{
1134 g_cfg->cdr.interval = atoi(argv[0]);
1135 return CMD_SUCCESS;
1136}
1137
Philippf1f34362016-08-26 17:00:21 +02001138#define COMPRESSION_STR "Configure compression\n"
1139DEFUN(cfg_no_comp_rfc1144, cfg_no_comp_rfc1144_cmd,
1140 "no compression rfc1144",
1141 NO_STR COMPRESSION_STR "disable rfc1144 TCP/IP header compression\n")
1142{
1143 g_cfg->pcomp_rfc1144.active = 0;
1144 g_cfg->pcomp_rfc1144.passive = 0;
1145 return CMD_SUCCESS;
1146}
1147
1148DEFUN(cfg_comp_rfc1144, cfg_comp_rfc1144_cmd,
1149 "compression rfc1144 active slots <1-256>",
1150 COMPRESSION_STR
1151 "RFC1144 Header compresion scheme\n"
1152 "Compression is actively proposed\n"
1153 "Number of compression state slots\n"
1154 "Number of compression state slots\n")
1155{
1156 g_cfg->pcomp_rfc1144.active = 1;
1157 g_cfg->pcomp_rfc1144.passive = 1;
1158 g_cfg->pcomp_rfc1144.s01 = atoi(argv[0]) - 1;
1159 return CMD_SUCCESS;
1160}
1161
1162DEFUN(cfg_comp_rfc1144p, cfg_comp_rfc1144p_cmd,
1163 "compression rfc1144 passive",
1164 COMPRESSION_STR
1165 "RFC1144 Header compresion scheme\n"
1166 "Compression is available on request\n")
1167{
1168 g_cfg->pcomp_rfc1144.active = 0;
1169 g_cfg->pcomp_rfc1144.passive = 1;
1170 return CMD_SUCCESS;
1171}
1172
Philipp73f83d52016-09-02 13:38:01 +02001173DEFUN(cfg_no_comp_v42bis, cfg_no_comp_v42bis_cmd,
1174 "no compression v42bis",
1175 NO_STR COMPRESSION_STR "disable V.42bis data compression\n")
1176{
1177 g_cfg->dcomp_v42bis.active = 0;
1178 g_cfg->dcomp_v42bis.passive = 0;
1179 return CMD_SUCCESS;
1180}
1181
1182DEFUN(cfg_comp_v42bis, cfg_comp_v42bis_cmd,
1183 "compression v42bis active direction (ms|sgsn|both) codewords <512-65535> strlen <6-250>",
1184 COMPRESSION_STR
1185 "V.42bis data compresion scheme\n"
1186 "Compression is actively proposed\n"
1187 "Direction in which the compression shall be active (p0)\n"
1188 "Compress ms->sgsn direction only\n"
1189 "Compress sgsn->ms direction only\n"
1190 "Both directions\n"
1191 "Number of codewords (p1)\n"
1192 "Number of codewords\n"
1193 "Maximum string length (p2)\n" "Maximum string length\n")
1194{
1195 g_cfg->dcomp_v42bis.active = 1;
1196 g_cfg->dcomp_v42bis.passive = 1;
1197
1198 switch (argv[0][0]) {
1199 case 'm':
1200 g_cfg->dcomp_v42bis.p0 = 1;
1201 break;
1202 case 's':
1203 g_cfg->dcomp_v42bis.p0 = 2;
1204 break;
1205 case 'b':
1206 g_cfg->dcomp_v42bis.p0 = 3;
1207 break;
1208 }
1209
1210 g_cfg->dcomp_v42bis.p1 = atoi(argv[1]);
1211 g_cfg->dcomp_v42bis.p2 = atoi(argv[2]);
1212 return CMD_SUCCESS;
1213}
1214
1215DEFUN(cfg_comp_v42bisp, cfg_comp_v42bisp_cmd,
1216 "compression v42bis passive",
1217 COMPRESSION_STR
1218 "V.42bis data compresion scheme\n"
1219 "Compression is available on request\n")
1220{
1221 g_cfg->dcomp_v42bis.active = 0;
1222 g_cfg->dcomp_v42bis.passive = 1;
1223 return CMD_SUCCESS;
1224}
1225
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001226int sgsn_vty_init(struct sgsn_config *cfg)
Harald Welte288be162010-05-01 16:48:27 +02001227{
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001228 g_cfg = cfg;
1229
Harald Welted193cb32010-05-17 22:58:03 +02001230 install_element_ve(&show_sgsn_cmd);
1231 //install_element_ve(&show_mmctx_tlli_cmd);
1232 install_element_ve(&show_mmctx_imsi_cmd);
1233 install_element_ve(&show_mmctx_all_cmd);
1234 install_element_ve(&show_pdpctx_all_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001235 install_element_ve(&show_subscr_cache_cmd);
1236
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01001237 install_element(ENABLE_NODE, &update_subscr_insert_auth_triplet_cmd);
Jacob Erlbeckd9193432015-01-19 14:11:46 +01001238 install_element(ENABLE_NODE, &update_subscr_create_cmd);
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001239 install_element(ENABLE_NODE, &update_subscr_destroy_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001240 install_element(ENABLE_NODE, &update_subscr_cancel_cmd);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001241 install_element(ENABLE_NODE, &update_subscr_update_location_result_cmd);
1242 install_element(ENABLE_NODE, &update_subscr_update_auth_info_cmd);
Harald Welte288be162010-05-01 16:48:27 +02001243
1244 install_element(CONFIG_NODE, &cfg_sgsn_cmd);
1245 install_node(&sgsn_node, config_write_sgsn);
Jacob Erlbeck36722e12013-10-29 09:30:30 +01001246 vty_install_default(SGSN_NODE);
Harald Weltee300d002010-06-02 12:41:34 +02001247 install_element(SGSN_NODE, &cfg_sgsn_bind_addr_cmd);
Harald Welted193cb32010-05-17 22:58:03 +02001248 install_element(SGSN_NODE, &cfg_ggsn_remote_ip_cmd);
1249 //install_element(SGSN_NODE, &cfg_ggsn_remote_port_cmd);
1250 install_element(SGSN_NODE, &cfg_ggsn_gtp_version_cmd);
Harald Welte7f6da482013-03-19 11:00:13 +01001251 install_element(SGSN_NODE, &cfg_imsi_acl_cmd);
Harald Welte3dfb5492013-03-19 11:48:54 +01001252 install_element(SGSN_NODE, &cfg_auth_policy_cmd);
Max93408ae2016-06-28 14:10:16 +02001253 install_element(SGSN_NODE, &cfg_encrypt_cmd);
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001254 install_element(SGSN_NODE, &cfg_gsup_remote_ip_cmd);
1255 install_element(SGSN_NODE, &cfg_gsup_remote_port_cmd);
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001256 install_element(SGSN_NODE, &cfg_gsup_oap_id_cmd);
1257 install_element(SGSN_NODE, &cfg_gsup_oap_k_cmd);
1258 install_element(SGSN_NODE, &cfg_gsup_oap_opc_cmd);
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +01001259 install_element(SGSN_NODE, &cfg_apn_ggsn_cmd);
1260 install_element(SGSN_NODE, &cfg_apn_imsi_ggsn_cmd);
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001261 install_element(SGSN_NODE, &cfg_apn_name_cmd);
1262 install_element(SGSN_NODE, &cfg_no_apn_name_cmd);
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001263 install_element(SGSN_NODE, &cfg_cdr_filename_cmd);
1264 install_element(SGSN_NODE, &cfg_no_cdr_filename_cmd);
1265 install_element(SGSN_NODE, &cfg_cdr_interval_cmd);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001266 install_element(SGSN_NODE, &cfg_ggsn_dynamic_lookup_cmd);
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +08001267 install_element(SGSN_NODE, &cfg_grx_ggsn_cmd);
Harald Welte288be162010-05-01 16:48:27 +02001268
Harald Welte94508822015-08-15 19:08:21 +02001269 install_element(SGSN_NODE, &cfg_sgsn_T3312_cmd);
1270 install_element(SGSN_NODE, &cfg_sgsn_T3322_cmd);
1271 install_element(SGSN_NODE, &cfg_sgsn_T3350_cmd);
1272 install_element(SGSN_NODE, &cfg_sgsn_T3360_cmd);
1273 install_element(SGSN_NODE, &cfg_sgsn_T3370_cmd);
1274 install_element(SGSN_NODE, &cfg_sgsn_T3313_cmd);
1275 install_element(SGSN_NODE, &cfg_sgsn_T3314_cmd);
1276 install_element(SGSN_NODE, &cfg_sgsn_T3316_cmd);
1277 install_element(SGSN_NODE, &cfg_sgsn_T3385_cmd);
1278 install_element(SGSN_NODE, &cfg_sgsn_T3386_cmd);
1279 install_element(SGSN_NODE, &cfg_sgsn_T3395_cmd);
1280 install_element(SGSN_NODE, &cfg_sgsn_T3397_cmd);
1281
Philippf1f34362016-08-26 17:00:21 +02001282 install_element(SGSN_NODE, &cfg_no_comp_rfc1144_cmd);
1283 install_element(SGSN_NODE, &cfg_comp_rfc1144_cmd);
1284 install_element(SGSN_NODE, &cfg_comp_rfc1144p_cmd);
Philipp73f83d52016-09-02 13:38:01 +02001285 install_element(SGSN_NODE, &cfg_no_comp_v42bis_cmd);
1286 install_element(SGSN_NODE, &cfg_comp_v42bis_cmd);
1287 install_element(SGSN_NODE, &cfg_comp_v42bisp_cmd);
Neels Hofmeyr2188a772016-05-20 21:59:55 +02001288
1289#ifdef BUILD_IU
Neels Hofmeyra7a39472017-07-05 15:19:52 +02001290 ranap_iu_vty_init(SGSN_NODE, &g_cfg->iu.rab_assign_addr_enc);
Neels Hofmeyr2188a772016-05-20 21:59:55 +02001291#endif
Harald Welte288be162010-05-01 16:48:27 +02001292 return 0;
1293}
1294
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001295int sgsn_parse_config(const char *config_file)
Harald Welte288be162010-05-01 16:48:27 +02001296{
1297 int rc;
1298
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001299 /* make sure sgsn_vty_init() was called before this */
1300 OSMO_ASSERT(g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +01001301
Harald Welte94508822015-08-15 19:08:21 +02001302 g_cfg->timers.T3312 = GSM0408_T3312_SECS;
1303 g_cfg->timers.T3322 = GSM0408_T3322_SECS;
1304 g_cfg->timers.T3350 = GSM0408_T3350_SECS;
1305 g_cfg->timers.T3360 = GSM0408_T3360_SECS;
1306 g_cfg->timers.T3370 = GSM0408_T3370_SECS;
1307 g_cfg->timers.T3313 = GSM0408_T3313_SECS;
1308 g_cfg->timers.T3314 = GSM0408_T3314_SECS;
1309 g_cfg->timers.T3316 = GSM0408_T3316_SECS;
1310 g_cfg->timers.T3385 = GSM0408_T3385_SECS;
1311 g_cfg->timers.T3386 = GSM0408_T3386_SECS;
1312 g_cfg->timers.T3395 = GSM0408_T3395_SECS;
1313 g_cfg->timers.T3397 = GSM0408_T3397_SECS;
1314
Harald Weltedcccb182010-05-16 20:52:23 +02001315 rc = vty_read_config_file(config_file, NULL);
Harald Welte288be162010-05-01 16:48:27 +02001316 if (rc < 0) {
1317 fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
1318 return rc;
1319 }
1320
Neels Hofmeyr27355c92017-02-24 06:28:31 +01001321 if (g_cfg->auth_policy == SGSN_AUTH_POLICY_REMOTE
1322 && !(g_cfg->gsup_server_addr.sin_addr.s_addr
1323 && g_cfg->gsup_server_port)) {
1324 fprintf(stderr, "Configuration error:"
1325 " 'auth-policy remote' requires both"
1326 " 'gsup remote-ip' and 'gsup remote-port'\n");
1327 return -EINVAL;
1328 }
1329
Harald Welte288be162010-05-01 16:48:27 +02001330 return 0;
1331}