blob: cf44cc420d7558eb6932db78270997533a888370 [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
33#include <openbsc/debug.h>
34#include <openbsc/sgsn.h>
Harald Welteea34a4e2012-06-16 14:59:56 +080035#include <osmocom/gprs/gprs_ns.h>
Harald Welted193cb32010-05-17 22:58:03 +020036#include <openbsc/gprs_sgsn.h>
Harald Welte62ab20c2010-05-14 18:59:17 +020037#include <openbsc/vty.h>
Neels Hofmeyreaaee922016-12-08 21:22:58 +010038#include <openbsc/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
51#include <openbsc/iu.h>
52#endif
53
Harald Welte288be162010-05-01 16:48:27 +020054static struct sgsn_config *g_cfg = NULL;
55
Jacob Erlbeck106f5472014-11-04 10:08:37 +010056const struct value_string sgsn_auth_pol_strs[] = {
57 { SGSN_AUTH_POLICY_OPEN, "accept-all" },
58 { SGSN_AUTH_POLICY_CLOSED, "closed" },
59 { SGSN_AUTH_POLICY_ACL_ONLY, "acl-only" },
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +010060 { SGSN_AUTH_POLICY_REMOTE, "remote" },
Jacob Erlbeck106f5472014-11-04 10:08:37 +010061 { 0, NULL }
62};
63
Harald Welte94508822015-08-15 19:08:21 +020064/* Section 11.2.2 / Table 11.3a GPRS Mobility management timers – MS side */
65#define GSM0408_T3312_SECS (10*60) /* periodic RAU interval, default 54min */
66
67/* Section 11.2.2 / Table 11.4 MM timers netwokr side */
68#define GSM0408_T3322_SECS 6 /* DETACH_REQ -> DETACH_ACC */
69#define GSM0408_T3350_SECS 6 /* waiting for ATT/RAU/TMSI COMPL */
70#define GSM0408_T3360_SECS 6 /* waiting for AUTH/CIPH RESP */
71#define GSM0408_T3370_SECS 6 /* waiting for ID RESP */
72
Alexander Couzens5ba6fb32017-01-31 18:04:27 +010073/* Section 11.2.2 / Table 11.4a MM timers network side */
Harald Welte94508822015-08-15 19:08:21 +020074#define GSM0408_T3313_SECS 30 /* waiting for paging response */
75#define GSM0408_T3314_SECS 44 /* force to STBY on expiry, Ready timer */
76#define GSM0408_T3316_SECS 44
77
78/* Section 11.3 / Table 11.2d Timers of Session Management - network side */
79#define GSM0408_T3385_SECS 8 /* wait for ACT PDP CTX REQ */
80#define GSM0408_T3386_SECS 8 /* wait for MODIFY PDP CTX ACK */
81#define GSM0408_T3395_SECS 8 /* wait for DEACT PDP CTX ACK */
82#define GSM0408_T3397_SECS 8 /* wait for DEACT AA PDP CTX ACK */
83
84#define DECLARE_TIMER(number, doc) \
85 DEFUN(cfg_sgsn_T##number, \
86 cfg_sgsn_T##number##_cmd, \
87 "timer t" #number " <0-65535>", \
88 "Configure GPRS Timers\n" \
Holger Hans Peter Freytherfe60cfb2015-11-02 12:55:07 +010089 doc "\nTimer Value in seconds\n") \
Harald Welte94508822015-08-15 19:08:21 +020090{ \
91 int value = atoi(argv[0]); \
92 \
93 if (value < 0 || value > 65535) { \
94 vty_out(vty, "Timer value %s out of range.%s", \
95 argv[0], VTY_NEWLINE); \
96 return CMD_WARNING; \
97 } \
98 \
99 g_cfg->timers.T##number = value; \
100 return CMD_SUCCESS; \
101}
102
103DECLARE_TIMER(3312, "Periodic RA Update timer (s)")
Neels Hofmeyr65482c92015-10-19 14:37:12 +0200104DECLARE_TIMER(3322, "Detach request -> accept timer (s)")
Harald Welte94508822015-08-15 19:08:21 +0200105DECLARE_TIMER(3350, "Waiting for ATT/RAU/TMSI_COMPL timer (s)")
106DECLARE_TIMER(3360, "Waiting for AUTH/CIPH response timer (s)")
107DECLARE_TIMER(3370, "Waiting for IDENTITY response timer (s)")
108
109DECLARE_TIMER(3313, "Waiting for paging response timer (s)")
110DECLARE_TIMER(3314, "Force to STANDBY on expiry timer (s)")
Holger Hans Peter Freytherfe60cfb2015-11-02 12:55:07 +0100111DECLARE_TIMER(3316, "AA-Ready timer (s)")
Harald Welte94508822015-08-15 19:08:21 +0200112
113DECLARE_TIMER(3385, "Wait for ACT PDP CTX REQ timer (s)")
114DECLARE_TIMER(3386, "Wait for MODIFY PDP CTX ACK timer (s)")
115DECLARE_TIMER(3395, "Wait for DEACT PDP CTX ACK timer (s)")
116DECLARE_TIMER(3397, "Wait for DEACT AA PDP CTX ACK timer (s)")
117
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100118
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200119#define GSM48_MAX_APN_LEN 102 /* 10.5.6.1 */
Neels Hofmeyr30f7bcb2015-11-08 20:34:47 +0100120/** Copy apn to a static buffer, replacing the length octets in apn_enc with '.'
121 * and terminating with a '\0'. Return the static buffer.
122 * len: the length of the encoded APN (which has no terminating zero).
123 */
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200124static char *gprs_apn2str(uint8_t *apn, unsigned int len)
125{
126 static char apnbuf[GSM48_MAX_APN_LEN+1];
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200127
128 if (!apn)
129 return "";
Harald Welte7e82b742017-08-12 13:43:54 +0200130 osmo_apn_to_str(apnbuf, apn, len);
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200131
132 return apnbuf+1;
133}
134
Holger Hans Peter Freythera2730302014-03-23 18:08:26 +0100135char *gprs_pdpaddr2str(uint8_t *pdpa, uint8_t len)
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200136{
137 static char str[INET6_ADDRSTRLEN + 10];
138
139 if (!pdpa || len < 2)
140 return "none";
141
142 switch (pdpa[0] & 0x0f) {
143 case PDP_TYPE_ORG_IETF:
144 switch (pdpa[1]) {
145 case PDP_TYPE_N_IETF_IPv4:
146 if (len < 2 + 4)
147 break;
148 strcpy(str, "IPv4 ");
149 inet_ntop(AF_INET, pdpa+2, str+5, sizeof(str)-5);
150 return str;
151 case PDP_TYPE_N_IETF_IPv6:
152 if (len < 2 + 8)
153 break;
154 strcpy(str, "IPv6 ");
155 inet_ntop(AF_INET6, pdpa+2, str+5, sizeof(str)-5);
156 return str;
157 default:
158 break;
159 }
160 break;
161 case PDP_TYPE_ORG_ETSI:
162 if (pdpa[1] == PDP_TYPE_N_ETSI_PPP)
163 return "PPP";
164 break;
165 default:
166 break;
167 }
168
169 return "invalid";
170}
171
Harald Welte288be162010-05-01 16:48:27 +0200172static struct cmd_node sgsn_node = {
173 SGSN_NODE,
Harald Welte570ce242012-08-17 13:16:10 +0200174 "%s(config-sgsn)# ",
Harald Welte288be162010-05-01 16:48:27 +0200175 1,
176};
177
178static int config_write_sgsn(struct vty *vty)
179{
Harald Welte77289c22010-05-18 14:32:29 +0200180 struct sgsn_ggsn_ctx *gctx;
Harald Welte7f6da482013-03-19 11:00:13 +0100181 struct imsi_acl_entry *acl;
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100182 struct apn_ctx *actx;
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800183 struct ares_addr_node *server;
Harald Welte288be162010-05-01 16:48:27 +0200184
185 vty_out(vty, "sgsn%s", VTY_NEWLINE);
186
Harald Weltee300d002010-06-02 12:41:34 +0200187 vty_out(vty, " gtp local-ip %s%s",
188 inet_ntoa(g_cfg->gtp_listenaddr.sin_addr), VTY_NEWLINE);
189
Harald Welted193cb32010-05-17 22:58:03 +0200190 llist_for_each_entry(gctx, &sgsn_ggsn_ctxts, list) {
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800191 if (gctx->id == UINT32_MAX)
192 continue;
193
Harald Welteff3bde82010-05-19 15:09:09 +0200194 vty_out(vty, " ggsn %u remote-ip %s%s", gctx->id,
Harald Welted193cb32010-05-17 22:58:03 +0200195 inet_ntoa(gctx->remote_addr), VTY_NEWLINE);
Harald Welteff3bde82010-05-19 15:09:09 +0200196 vty_out(vty, " ggsn %u gtp-version %u%s", gctx->id,
Harald Welted193cb32010-05-17 22:58:03 +0200197 gctx->gtp_version, VTY_NEWLINE);
Harald Welte288be162010-05-01 16:48:27 +0200198 }
199
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800200 if (sgsn->cfg.dynamic_lookup)
201 vty_out(vty, " ggsn dynamic%s", VTY_NEWLINE);
202
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800203 for (server = sgsn->ares_servers; server; server = server->next)
204 vty_out(vty, " grx-dns-add %s%s", inet_ntoa(server->addr.addr4), VTY_NEWLINE);
205
Max93408ae2016-06-28 14:10:16 +0200206 if (g_cfg->cipher != GPRS_ALGO_GEA0)
207 vty_out(vty, " encryption %s%s",
208 get_value_string(gprs_cipher_names, g_cfg->cipher),
209 VTY_NEWLINE);
Jacob Erlbeck39f040d2014-12-18 12:46:47 +0100210 if (g_cfg->gsup_server_addr.sin_addr.s_addr)
211 vty_out(vty, " gsup remote-ip %s%s",
212 inet_ntoa(g_cfg->gsup_server_addr.sin_addr), VTY_NEWLINE);
213 if (g_cfg->gsup_server_port)
214 vty_out(vty, " gsup remote-port %d%s",
215 g_cfg->gsup_server_port, VTY_NEWLINE);
Max176b62a2016-07-04 11:09:07 +0200216 vty_out(vty, " auth-policy %s%s",
217 get_value_string(sgsn_auth_pol_strs, g_cfg->auth_policy),
218 VTY_NEWLINE);
Neels Hofmeyr568a7272015-10-12 11:57:38 +0200219
220 vty_out(vty, " gsup oap-id %d%s",
221 (int)g_cfg->oap.client_id, VTY_NEWLINE);
222 if (g_cfg->oap.secret_k_present != 0)
223 vty_out(vty, " gsup oap-k %s%s",
224 osmo_hexdump_nospc(g_cfg->oap.secret_k, sizeof(g_cfg->oap.secret_k)),
225 VTY_NEWLINE);
226 if (g_cfg->oap.secret_opc_present != 0)
227 vty_out(vty, " gsup oap-opc %s%s",
228 osmo_hexdump_nospc(g_cfg->oap.secret_opc, sizeof(g_cfg->oap.secret_opc)),
229 VTY_NEWLINE);
230
Harald Welte7f6da482013-03-19 11:00:13 +0100231 llist_for_each_entry(acl, &g_cfg->imsi_acl, list)
232 vty_out(vty, " imsi-acl add %s%s", acl->imsi, VTY_NEWLINE);
233
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100234 if (llist_empty(&sgsn_apn_ctxts))
235 vty_out(vty, " ! apn * ggsn 0%s", VTY_NEWLINE);
236 llist_for_each_entry(actx, &sgsn_apn_ctxts, list) {
237 if (strlen(actx->imsi_prefix) > 0)
Holger Hans Peter Freytherb7ae0b32015-05-29 15:11:55 +0200238 vty_out(vty, " apn %s imsi-prefix %s ggsn %u%s",
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100239 actx->name, actx->imsi_prefix, actx->ggsn->id,
240 VTY_NEWLINE);
241 else
Holger Hans Peter Freytherb7ae0b32015-05-29 15:11:55 +0200242 vty_out(vty, " apn %s ggsn %u%s", actx->name,
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100243 actx->ggsn->id, VTY_NEWLINE);
244 }
245
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +0200246 if (g_cfg->cdr.filename)
247 vty_out(vty, " cdr filename %s%s", g_cfg->cdr.filename, VTY_NEWLINE);
248 else
249 vty_out(vty, " no cdr filename%s", VTY_NEWLINE);
250 vty_out(vty, " cdr interval %d%s", g_cfg->cdr.interval, VTY_NEWLINE);
251
Harald Welte94508822015-08-15 19:08:21 +0200252 vty_out(vty, " timer t3312 %d%s", g_cfg->timers.T3312, VTY_NEWLINE);
253 vty_out(vty, " timer t3322 %d%s", g_cfg->timers.T3322, VTY_NEWLINE);
254 vty_out(vty, " timer t3350 %d%s", g_cfg->timers.T3350, VTY_NEWLINE);
255 vty_out(vty, " timer t3360 %d%s", g_cfg->timers.T3360, VTY_NEWLINE);
256 vty_out(vty, " timer t3370 %d%s", g_cfg->timers.T3370, VTY_NEWLINE);
257 vty_out(vty, " timer t3313 %d%s", g_cfg->timers.T3313, VTY_NEWLINE);
258 vty_out(vty, " timer t3314 %d%s", g_cfg->timers.T3314, VTY_NEWLINE);
259 vty_out(vty, " timer t3316 %d%s", g_cfg->timers.T3316, VTY_NEWLINE);
260 vty_out(vty, " timer t3385 %d%s", g_cfg->timers.T3385, VTY_NEWLINE);
261 vty_out(vty, " timer t3386 %d%s", g_cfg->timers.T3386, VTY_NEWLINE);
262 vty_out(vty, " timer t3395 %d%s", g_cfg->timers.T3395, VTY_NEWLINE);
263 vty_out(vty, " timer t3397 %d%s", g_cfg->timers.T3397, VTY_NEWLINE);
264
Philippf1f34362016-08-26 17:00:21 +0200265 if (g_cfg->pcomp_rfc1144.active) {
266 vty_out(vty, " compression rfc1144 active slots %d%s",
267 g_cfg->pcomp_rfc1144.s01 + 1, VTY_NEWLINE);
268 } else if (g_cfg->pcomp_rfc1144.passive) {
269 vty_out(vty, " compression rfc1144 passive%s", VTY_NEWLINE);
270 } else
271 vty_out(vty, " no compression rfc1144%s", VTY_NEWLINE);
272
Philipp73f83d52016-09-02 13:38:01 +0200273 if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 1) {
274 vty_out(vty,
275 " compression v42bis active direction sgsn 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.active && g_cfg->dcomp_v42bis.p0 == 2) {
279 vty_out(vty,
280 " compression v42bis active direction ms codewords %d strlen %d%s",
281 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
282 VTY_NEWLINE);
283 } else if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 3) {
284 vty_out(vty,
285 " compression v42bis active direction both codewords %d strlen %d%s",
286 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
287 VTY_NEWLINE);
288 } else if (g_cfg->dcomp_v42bis.passive) {
289 vty_out(vty, " compression v42bis passive%s", VTY_NEWLINE);
290 } else
291 vty_out(vty, " no compression v42bis%s", VTY_NEWLINE);
292
Neels Hofmeyr2188a772016-05-20 21:59:55 +0200293#ifdef BUILD_IU
294 iu_vty_config_write(vty, " ");
295#endif
296
Harald Welte288be162010-05-01 16:48:27 +0200297 return CMD_SUCCESS;
298}
299
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100300#define SGSN_STR "Configure the SGSN\n"
301#define GGSN_STR "Configure the GGSN information\n"
Harald Weltee300d002010-06-02 12:41:34 +0200302
303DEFUN(cfg_sgsn, cfg_sgsn_cmd,
304 "sgsn",
305 SGSN_STR)
Harald Welte288be162010-05-01 16:48:27 +0200306{
307 vty->node = SGSN_NODE;
308 return CMD_SUCCESS;
309}
310
Harald Weltee300d002010-06-02 12:41:34 +0200311DEFUN(cfg_sgsn_bind_addr, cfg_sgsn_bind_addr_cmd,
312 "gtp local-ip A.B.C.D",
313 "GTP Parameters\n"
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100314 "Set the IP address for the local GTP bind\n"
315 "IPv4 Address\n")
Harald Weltee300d002010-06-02 12:41:34 +0200316{
317 inet_aton(argv[0], &g_cfg->gtp_listenaddr.sin_addr);
318
319 return CMD_SUCCESS;
320}
321
Harald Welted193cb32010-05-17 22:58:03 +0200322DEFUN(cfg_ggsn_remote_ip, cfg_ggsn_remote_ip_cmd,
323 "ggsn <0-255> remote-ip A.B.C.D",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100324 GGSN_STR "GGSN Number\n" IP_STR "IPv4 Address\n")
Harald Welted193cb32010-05-17 22:58:03 +0200325{
326 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200327 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welte288be162010-05-01 16:48:27 +0200328
Harald Welted193cb32010-05-17 22:58:03 +0200329 inet_aton(argv[1], &ggc->remote_addr);
Harald Welte288be162010-05-01 16:48:27 +0200330
Harald Welted193cb32010-05-17 22:58:03 +0200331 return CMD_SUCCESS;
332}
333
334#if 0
335DEFUN(cfg_ggsn_remote_port, cfg_ggsn_remote_port_cmd,
336 "ggsn <0-255> remote-port <0-65535>",
337 "")
338{
339 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200340 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welted193cb32010-05-17 22:58:03 +0200341 uint16_t port = atoi(argv[1]);
342
343}
344#endif
345
346DEFUN(cfg_ggsn_gtp_version, cfg_ggsn_gtp_version_cmd,
347 "ggsn <0-255> gtp-version (0|1)",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100348 GGSN_STR "GGSN Number\n" "GTP Version\n"
349 "Version 0\n" "Version 1\n")
Harald Welted193cb32010-05-17 22:58:03 +0200350{
351 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200352 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welted193cb32010-05-17 22:58:03 +0200353
354 if (atoi(argv[1]))
355 ggc->gtp_version = 1;
356 else
357 ggc->gtp_version = 0;
358
359 return CMD_SUCCESS;
360}
361
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800362DEFUN(cfg_ggsn_dynamic_lookup, cfg_ggsn_dynamic_lookup_cmd,
363 "ggsn dynamic",
364 GGSN_STR "Enable dynamic GRX based look-up (requires restart)\n")
365{
366 sgsn->cfg.dynamic_lookup = 1;
367 return CMD_SUCCESS;
368}
369
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800370DEFUN(cfg_grx_ggsn, cfg_grx_ggsn_cmd,
371 "grx-dns-add A.B.C.D",
372 "Add DNS server\nIPv4 address\n")
373{
374 struct ares_addr_node *node = talloc_zero(tall_bsc_ctx, struct ares_addr_node);
375 node->family = AF_INET;
376 inet_aton(argv[0], &node->addr.addr4);
377
378 node->next = sgsn->ares_servers;
379 sgsn->ares_servers = node;
380 return CMD_SUCCESS;
381}
382
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100383#define APN_STR "Configure the information per APN\n"
384#define APN_GW_STR "The APN gateway name optionally prefixed by '*' (wildcard)\n"
385
386static int add_apn_ggsn_mapping(struct vty *vty, const char *apn_str,
387 const char *imsi_prefix, int ggsn_id)
388{
389 struct apn_ctx *actx;
390 struct sgsn_ggsn_ctx *ggsn;
391
392 ggsn = sgsn_ggsn_ctx_by_id(ggsn_id);
393 if (ggsn == NULL) {
394 vty_out(vty, "%% a GGSN with id %d has not been defined%s",
395 ggsn_id, VTY_NEWLINE);
396 return CMD_WARNING;
397 }
398
399 actx = sgsn_apn_ctx_find_alloc(apn_str, imsi_prefix);
400 if (!actx) {
401 vty_out(vty, "%% unable to create APN context for %s/%s%s",
402 apn_str, imsi_prefix, VTY_NEWLINE);
403 return CMD_WARNING;
404 }
405
406 actx->ggsn = ggsn;
407
408 return CMD_SUCCESS;
409}
410
Harald Welted193cb32010-05-17 22:58:03 +0200411DEFUN(cfg_apn_ggsn, cfg_apn_ggsn_cmd,
412 "apn APNAME ggsn <0-255>",
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100413 APN_STR APN_GW_STR
414 "Select the GGSN to use when the APN gateway prefix matches\n"
415 "The GGSN id")
Harald Welted193cb32010-05-17 22:58:03 +0200416{
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100417
418 return add_apn_ggsn_mapping(vty, argv[0], "", atoi(argv[1]));
Harald Welted193cb32010-05-17 22:58:03 +0200419}
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100420
421DEFUN(cfg_apn_imsi_ggsn, cfg_apn_imsi_ggsn_cmd,
422 "apn APNAME imsi-prefix IMSIPRE ggsn <0-255>",
423 APN_STR APN_GW_STR
424 "Restrict rule to a certain IMSI prefix\n"
425 "An IMSI prefix\n"
426 "Select the GGSN to use when APN gateway and IMSI prefix match\n"
427 "The GGSN id")
428{
429
430 return add_apn_ggsn_mapping(vty, argv[0], argv[1], atoi(argv[2]));
431}
Harald Welted193cb32010-05-17 22:58:03 +0200432
433const struct value_string gprs_mm_st_strs[] = {
434 { GMM_DEREGISTERED, "DEREGISTERED" },
435 { GMM_COMMON_PROC_INIT, "COMMON PROCEDURE (INIT)" },
436 { GMM_REGISTERED_NORMAL, "REGISTERED (NORMAL)" },
Harald Weltebffeff82010-06-09 15:50:45 +0200437 { GMM_REGISTERED_SUSPENDED, "REGISTERED (SUSPENDED)" },
Harald Welted193cb32010-05-17 22:58:03 +0200438 { GMM_DEREGISTERED_INIT, "DEREGISTERED (INIT)" },
439 { 0, NULL }
440};
441
Harald Welte471ac7d2016-12-15 19:48:58 +0100442static char *gtp_ntoa(struct ul16_t *ul)
443{
444 if (ul->l == 4) {
445 struct in_addr *ia = (struct in_addr *) ul;
446 return inet_ntoa(*ia);
447 } else {
448 return "UNKNOWN";
449 }
450}
451
Harald Welted193cb32010-05-17 22:58:03 +0200452static void vty_dump_pdp(struct vty *vty, const char *pfx,
453 struct sgsn_pdp_ctx *pdp)
454{
Jacob Erlbeck99985b52014-10-13 10:32:00 +0200455 const char *imsi = pdp->mm ? pdp->mm->imsi : "(detaching)";
Harald Welte471ac7d2016-12-15 19:48:58 +0100456 vty_out(vty, "%sPDP Context IMSI: %s, SAPI: %u, NSAPI: %u, TI: %u%s",
457 pfx, imsi, pdp->sapi, pdp->nsapi, pdp->ti, VTY_NEWLINE);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200458 if (pdp->lib) {
459 vty_out(vty, "%s APN: %s%s", pfx,
460 gprs_apn2str(pdp->lib->apn_use.v, pdp->lib->apn_use.l),
461 VTY_NEWLINE);
462 vty_out(vty, "%s PDP Address: %s%s", pfx,
463 gprs_pdpaddr2str(pdp->lib->eua.v, pdp->lib->eua.l),
464 VTY_NEWLINE);
465 vty_out(vty, "%s GTP Local Control(%s / TEIC: 0x%08x) ", pfx,
466 gtp_ntoa(&pdp->lib->gsnlc), pdp->lib->teic_own);
467 vty_out(vty, "Data(%s / TEID: 0x%08x)%s",
468 gtp_ntoa(&pdp->lib->gsnlu), pdp->lib->teid_own, VTY_NEWLINE);
469 vty_out(vty, "%s GTP Remote Control(%s / TEIC: 0x%08x) ", pfx,
470 gtp_ntoa(&pdp->lib->gsnrc), pdp->lib->teic_gn);
471 vty_out(vty, "Data(%s / TEID: 0x%08x)%s",
472 gtp_ntoa(&pdp->lib->gsnru), pdp->lib->teid_gn, VTY_NEWLINE);
473 }
Harald Welte471ac7d2016-12-15 19:48:58 +0100474
Harald Welteefbdee92010-06-10 00:20:12 +0200475 vty_out_rate_ctr_group(vty, " ", pdp->ctrg);
Harald Welted193cb32010-05-17 22:58:03 +0200476}
477
478static void vty_dump_mmctx(struct vty *vty, const char *pfx,
479 struct sgsn_mm_ctx *mm, int pdp)
480{
481 vty_out(vty, "%sMM Context for IMSI %s, IMEI %s, P-TMSI %08x%s",
482 pfx, mm->imsi, mm->imei, mm->p_tmsi, VTY_NEWLINE);
Holger Hans Peter Freyther8ee13e22015-05-18 10:00:03 +0200483 vty_out(vty, "%s MSISDN: %s, TLLI: %08x%s HLR: %s",
Harald Weltef97ee042015-12-25 19:12:21 +0100484 pfx, mm->msisdn, mm->gb.tlli, mm->hlr, VTY_NEWLINE);
Harald Welted193cb32010-05-17 22:58:03 +0200485 vty_out(vty, "%s MM State: %s, Routeing Area: %u-%u-%u-%u, "
486 "Cell ID: %u%s", pfx,
Alexander Couzens4f8da6d2017-01-31 15:34:26 +0100487 get_value_string(gprs_mm_st_strs, mm->gmm_state),
Harald Welted193cb32010-05-17 22:58:03 +0200488 mm->ra.mcc, mm->ra.mnc, mm->ra.lac, mm->ra.rac,
Harald Weltef97ee042015-12-25 19:12:21 +0100489 mm->gb.cell_id, VTY_NEWLINE);
Harald Welted193cb32010-05-17 22:58:03 +0200490
Harald Welte8acd88f2010-05-18 10:57:45 +0200491 vty_out_rate_ctr_group(vty, " ", mm->ctrg);
492
Harald Welted193cb32010-05-17 22:58:03 +0200493 if (pdp) {
494 struct sgsn_pdp_ctx *pdp;
495
496 llist_for_each_entry(pdp, &mm->pdp_list, list)
497 vty_dump_pdp(vty, " ", pdp);
498 }
499}
500
501DEFUN(show_sgsn, show_sgsn_cmd, "show sgsn",
502 SHOW_STR "Display information about the SGSN")
503{
Jacob Erlbeck80547992014-12-19 19:19:46 +0100504 if (sgsn->gsup_client) {
505 struct ipa_client_conn *link = sgsn->gsup_client->link;
506 vty_out(vty,
507 " Remote authorization: %sconnected to %s:%d via GSUP%s",
508 sgsn->gsup_client->is_connected ? "" : "not ",
509 link->addr, link->port,
510 VTY_NEWLINE);
511 }
Harald Welted193cb32010-05-17 22:58:03 +0200512 /* FIXME: statistics */
513 return CMD_SUCCESS;
514}
515
516#define MMCTX_STR "MM Context\n"
517#define INCLUDE_PDP_STR "Include PDP Context Information\n"
518
519#if 0
520DEFUN(show_mmctx_tlli, show_mmctx_tlli_cmd,
521 "show mm-context tlli HEX [pdp]",
522 SHOW_STR MMCTX_STR "Identify by TLLI\n" "TLLI\n" INCLUDE_PDP_STR)
523{
524 uint32_t tlli;
525 struct sgsn_mm_ctx *mm;
526
527 tlli = strtoul(argv[0], NULL, 16);
528 mm = sgsn_mm_ctx_by_tlli(tlli);
529 if (!mm) {
530 vty_out(vty, "No MM context for TLLI %08x%s",
531 tlli, VTY_NEWLINE);
532 return CMD_WARNING;
533 }
534 vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
535 return CMD_SUCCESS;
536}
537#endif
538
539DEFUN(swow_mmctx_imsi, show_mmctx_imsi_cmd,
540 "show mm-context imsi IMSI [pdp]",
541 SHOW_STR MMCTX_STR "Identify by IMSI\n" "IMSI of the MM Context\n"
542 INCLUDE_PDP_STR)
543{
544 struct sgsn_mm_ctx *mm;
545
546 mm = sgsn_mm_ctx_by_imsi(argv[0]);
547 if (!mm) {
548 vty_out(vty, "No MM context for IMSI %s%s",
549 argv[0], VTY_NEWLINE);
550 return CMD_WARNING;
551 }
552 vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
553 return CMD_SUCCESS;
554}
555
556DEFUN(swow_mmctx_all, show_mmctx_all_cmd,
557 "show mm-context all [pdp]",
558 SHOW_STR MMCTX_STR "All MM Contexts\n" INCLUDE_PDP_STR)
559{
560 struct sgsn_mm_ctx *mm;
561
562 llist_for_each_entry(mm, &sgsn_mm_ctxts, list)
563 vty_dump_mmctx(vty, "", mm, argv[0] ? 1 : 0);
564
565 return CMD_SUCCESS;
566}
567
Harald Welted193cb32010-05-17 22:58:03 +0200568DEFUN(show_pdpctx_all, show_pdpctx_all_cmd,
569 "show pdp-context all",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100570 SHOW_STR "Display information on PDP Context\n" "Show everything\n")
Harald Welted193cb32010-05-17 22:58:03 +0200571{
572 struct sgsn_pdp_ctx *pdp;
573
574 llist_for_each_entry(pdp, &sgsn_pdp_ctxts, g_list)
575 vty_dump_pdp(vty, "", pdp);
576
577 return CMD_SUCCESS;
578}
Harald Welte288be162010-05-01 16:48:27 +0200579
Harald Welte7f6da482013-03-19 11:00:13 +0100580
581DEFUN(imsi_acl, cfg_imsi_acl_cmd,
582 "imsi-acl (add|del) IMSI",
583 "Access Control List of foreign IMSIs\n"
584 "Add IMSI to ACL\n"
585 "Remove IMSI from ACL\n"
586 "IMSI of subscriber\n")
587{
Philipp Maier6ee49d82017-02-28 16:53:07 +0100588 char imsi_sanitized[GSM23003_IMSI_MAX_DIGITS+1];
Harald Welte7f6da482013-03-19 11:00:13 +0100589 const char *op = argv[0];
Philipp Maier6ee49d82017-02-28 16:53:07 +0100590 const char *imsi = imsi_sanitized;
Harald Welte7f6da482013-03-19 11:00:13 +0100591 int rc;
592
Philipp Maier6ee49d82017-02-28 16:53:07 +0100593 /* Sanitize IMSI */
594 if (strlen(argv[1]) > GSM23003_IMSI_MAX_DIGITS) {
595 vty_out(vty, "%% IMSI (%s) too long -- ignored!%s",
596 argv[1], VTY_NEWLINE);
597 return CMD_WARNING;
598 }
599 memset(imsi_sanitized, '0', sizeof(imsi_sanitized));
600 strcpy(imsi_sanitized+GSM23003_IMSI_MAX_DIGITS-strlen(argv[1]),argv[1]);
601
Harald Welte7f6da482013-03-19 11:00:13 +0100602 if (!strcmp(op, "add"))
Jacob Erlbeck3b5d4072014-10-24 15:11:03 +0200603 rc = sgsn_acl_add(imsi, g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +0100604 else
Jacob Erlbeck3b5d4072014-10-24 15:11:03 +0200605 rc = sgsn_acl_del(imsi, g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +0100606
607 if (rc < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100608 vty_out(vty, "%% unable to %s ACL%s", op, VTY_NEWLINE);
Harald Welte7f6da482013-03-19 11:00:13 +0100609 return CMD_WARNING;
610 }
611
612 return CMD_SUCCESS;
613}
614
Max93408ae2016-06-28 14:10:16 +0200615DEFUN(cfg_encrypt, cfg_encrypt_cmd,
616 "encryption (GEA0|GEA1|GEA2|GEA3|GEA4)",
617 "Set encryption algorithm for SGSN\n"
618 "Use GEA0 (no encryption)\n"
619 "Use GEA1\nUse GEA2\nUse GEA3\nUse GEA4\n")
620{
Max93408ae2016-06-28 14:10:16 +0200621 enum gprs_ciph_algo c = get_string_value(gprs_cipher_names, argv[0]);
Max086067f2017-05-02 13:03:28 +0200622 if (c != GPRS_ALGO_GEA0) {
623 if (!gprs_cipher_supported(c)) {
624 vty_out(vty, "%% cipher %s is unsupported in current version%s", argv[0], VTY_NEWLINE);
625 return CMD_WARNING;
626 }
627
628 if (!g_cfg->require_authentication) {
629 vty_out(vty, "%% unable to use encryption %s without authentication: please adjust auth-policy%s",
630 argv[0], VTY_NEWLINE);
631 return CMD_WARNING;
632 }
Max93408ae2016-06-28 14:10:16 +0200633 }
634
635 g_cfg->cipher = c;
636
637 return CMD_SUCCESS;
638}
639
Harald Welte3dfb5492013-03-19 11:48:54 +0100640DEFUN(cfg_auth_policy, cfg_auth_policy_cmd,
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100641 "auth-policy (accept-all|closed|acl-only|remote)",
Harald Welte3dfb5492013-03-19 11:48:54 +0100642 "Autorization Policy of SGSN\n"
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100643 "Accept all IMSIs (DANGEROUS)\n"
644 "Accept only home network subscribers or those in the ACL\n"
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100645 "Accept only subscribers in the ACL\n"
646 "Use remote subscription data only (HLR)\n")
Harald Welte3dfb5492013-03-19 11:48:54 +0100647{
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100648 int val = get_string_value(sgsn_auth_pol_strs, argv[0]);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100649 OSMO_ASSERT(val >= SGSN_AUTH_POLICY_OPEN && val <= SGSN_AUTH_POLICY_REMOTE);
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100650 g_cfg->auth_policy = val;
Jacob Erlbeck9d4f46c2014-12-17 13:20:08 +0100651 g_cfg->require_authentication = (val == SGSN_AUTH_POLICY_REMOTE);
Jacob Erlbeck771573c2014-12-19 18:08:48 +0100652 g_cfg->require_update_location = (val == SGSN_AUTH_POLICY_REMOTE);
Harald Welte3dfb5492013-03-19 11:48:54 +0100653
654 return CMD_SUCCESS;
655}
656
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100657/* Subscriber */
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100658#include <openbsc/gprs_subscriber.h>
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100659
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100660static void subscr_dump_full_vty(struct vty *vty, struct gprs_subscr *gsub, int pending)
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100661{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100662#if 0
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100663 char expire_time[200];
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100664#endif
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100665 struct gsm_auth_tuple *at;
666 int at_idx;
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100667 struct sgsn_subscriber_pdp_data *pdp;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100668
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100669 vty_out(vty, " Authorized: %d%s",
670 gsub->authorized, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100671 vty_out(vty, " LAC: %d/0x%x%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100672 gsub->lac, gsub->lac, VTY_NEWLINE);
673 vty_out(vty, " IMSI: %s%s", gsub->imsi, VTY_NEWLINE);
674 if (gsub->tmsi != GSM_RESERVED_TMSI)
675 vty_out(vty, " TMSI: %08X%s", gsub->tmsi,
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100676 VTY_NEWLINE);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100677 if (gsub->sgsn_data->msisdn_len > 0)
Holger Hans Peter Freytherf7b38262015-04-23 16:58:33 -0400678 vty_out(vty, " MSISDN (BCD): %s%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100679 osmo_hexdump(gsub->sgsn_data->msisdn,
680 gsub->sgsn_data->msisdn_len),
Holger Hans Peter Freytherf7b38262015-04-23 16:58:33 -0400681 VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100682
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100683 if (strlen(gsub->imei) > 0)
684 vty_out(vty, " IMEI: %s%s", gsub->imei, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100685
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100686 for (at_idx = 0; at_idx < ARRAY_SIZE(gsub->sgsn_data->auth_triplets);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100687 at_idx++) {
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100688 at = &gsub->sgsn_data->auth_triplets[at_idx];
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100689 if (at->key_seq == GSM_KEY_SEQ_INVAL)
690 continue;
691
692 vty_out(vty, " A3A8 tuple (used %d times): ",
693 at->use_count);
Harald Welte89837d42016-05-06 23:28:11 +0200694 vty_out(vty, " CKSN: %d, ",
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100695 at->key_seq);
Harald Welte89837d42016-05-06 23:28:11 +0200696 if (at->vec.auth_types & OSMO_AUTH_TYPE_GSM) {
697 vty_out(vty, "RAND: %s, ",
698 osmo_hexdump(at->vec.rand,
699 sizeof(at->vec.rand)));
700 vty_out(vty, "SRES: %s, ",
701 osmo_hexdump(at->vec.sres,
702 sizeof(at->vec.sres)));
703 vty_out(vty, "Kc: %s%s",
704 osmo_hexdump(at->vec.kc,
705 sizeof(at->vec.kc)), VTY_NEWLINE);
706 }
707 if (at->vec.auth_types & OSMO_AUTH_TYPE_UMTS) {
708 vty_out(vty, " AUTN: %s, ",
709 osmo_hexdump(at->vec.autn,
710 sizeof(at->vec.autn)));
711 vty_out(vty, "RES: %s, ",
712 osmo_hexdump(at->vec.res, at->vec.res_len));
713 vty_out(vty, "IK: %s, ",
714 osmo_hexdump(at->vec.ik, sizeof(at->vec.ik)));
715 vty_out(vty, "CK: %s, ",
716 osmo_hexdump(at->vec.ck, sizeof(at->vec.ck)));
717 }
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100718 }
719
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100720 llist_for_each_entry(pdp, &gsub->sgsn_data->pdp_list, list) {
Holger Hans Peter Freytherd05e0692015-04-23 16:59:04 -0400721 vty_out(vty, " PDP info: Id: %d, Type: 0x%04x, APN: '%s' QoS: %s%s",
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100722 pdp->context_id, pdp->pdp_type, pdp->apn_str,
Holger Hans Peter Freytherd05e0692015-04-23 16:59:04 -0400723 osmo_hexdump(pdp->qos_subscribed, pdp->qos_subscribed_len),
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100724 VTY_NEWLINE);
725 }
726
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100727#if 0
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100728 /* print the expiration time of a subscriber */
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100729 if (gsub->expire_lu) {
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100730 strftime(expire_time, sizeof(expire_time),
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100731 "%a, %d %b %Y %T %z", localtime(&gsub->expire_lu));
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100732 expire_time[sizeof(expire_time) - 1] = '\0';
733 vty_out(vty, " Expiration Time: %s%s", expire_time, VTY_NEWLINE);
734 }
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100735#endif
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100736
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100737 if (gsub->flags)
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100738 vty_out(vty, " Flags: %s%s%s%s%s%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100739 gsub->flags & GPRS_SUBSCRIBER_FIRST_CONTACT ?
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100740 "FIRST_CONTACT " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100741 gsub->flags & GPRS_SUBSCRIBER_CANCELLED ?
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100742 "CANCELLED " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100743 gsub->flags & GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING ?
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100744 "UPDATE_LOCATION_PENDING " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100745 gsub->flags & GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING ?
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100746 "AUTH_INFO_PENDING " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100747 gsub->flags & GPRS_SUBSCRIBER_ENABLE_PURGE ?
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100748 "ENABLE_PURGE " : "",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100749 VTY_NEWLINE);
750
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100751 vty_out(vty, " Use count: %u%s", gsub->use_count, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100752}
753
754DEFUN(show_subscr_cache,
755 show_subscr_cache_cmd,
756 "show subscriber cache",
757 SHOW_STR "Show information about subscribers\n"
758 "Display contents of subscriber cache\n")
759{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100760 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100761
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100762 llist_for_each_entry(subscr, gprs_subscribers, entry) {
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100763 vty_out(vty, " Subscriber:%s", VTY_NEWLINE);
764 subscr_dump_full_vty(vty, subscr, 0);
765 }
766
767 return CMD_SUCCESS;
768}
769
770#define UPDATE_SUBSCR_STR "update-subscriber imsi IMSI "
771#define UPDATE_SUBSCR_HELP "Update subscriber list\n" \
772 "Use the IMSI to select the subscriber\n" \
773 "The IMSI\n"
774
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100775#define UPDATE_SUBSCR_INSERT_HELP "Insert data into the subscriber record\n"
776
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100777DEFUN(update_subscr_insert_auth_triplet, update_subscr_insert_auth_triplet_cmd,
778 UPDATE_SUBSCR_STR "insert auth-triplet <1-5> sres SRES rand RAND kc KC",
779 UPDATE_SUBSCR_HELP
780 UPDATE_SUBSCR_INSERT_HELP
781 "Update authentication triplet\n"
782 "Triplet index\n"
783 "Set SRES value\nSRES value (4 byte) in hex\n"
784 "Set RAND value\nRAND value (16 byte) in hex\n"
785 "Set Kc value\nKc value (8 byte) in hex\n")
786{
787 const char *imsi = argv[0];
788 const int cksn = atoi(argv[1]) - 1;
789 const char *sres_str = argv[2];
790 const char *rand_str = argv[3];
791 const char *kc_str = argv[4];
792 struct gsm_auth_tuple at = {0,};
793
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100794 struct gprs_subscr *subscr;
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100795
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100796 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100797 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100798 vty_out(vty, "%% unable get subscriber record for %s%s",
799 imsi, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100800 return CMD_WARNING;
801 }
802
803 OSMO_ASSERT(subscr->sgsn_data);
804
Harald Welte121e9a42016-04-20 13:13:19 +0200805 if (osmo_hexparse(sres_str, &at.vec.sres[0], sizeof(at.vec.sres)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100806 vty_out(vty, "%% invalid SRES value '%s'%s",
807 sres_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(rand_str, &at.vec.rand[0], sizeof(at.vec.rand)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100811 vty_out(vty, "%% invalid RAND value '%s'%s",
812 rand_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100813 goto failed;
814 }
Harald Welte121e9a42016-04-20 13:13:19 +0200815 if (osmo_hexparse(kc_str, &at.vec.kc[0], sizeof(at.vec.kc)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100816 vty_out(vty, "%% invalid Kc value '%s'%s",
817 kc_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100818 goto failed;
819 }
820 at.key_seq = cksn;
821
822 subscr->sgsn_data->auth_triplets[cksn] = at;
823 subscr->sgsn_data->auth_triplets_updated = 1;
824
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100825 gprs_subscr_put(subscr);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100826
827 return CMD_SUCCESS;
828
829failed:
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100830 gprs_subscr_put(subscr);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100831 return CMD_SUCCESS;
832}
833
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100834DEFUN(update_subscr_cancel, update_subscr_cancel_cmd,
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100835 UPDATE_SUBSCR_STR "cancel (update-procedure|subscription-withdraw)",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100836 UPDATE_SUBSCR_HELP
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100837 "Cancel (remove) subscriber record\n"
838 "The MS moved to another SGSN\n"
839 "The subscription is no longer valid\n")
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100840{
841 const char *imsi = argv[0];
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100842 const char *cancel_type = argv[1];
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100843
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100844 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100845
846 subscr = gprs_subscr_get_by_imsi(imsi);
847 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100848 vty_out(vty, "%% no subscriber record for %s%s",
849 imsi, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100850 return CMD_WARNING;
851 }
852
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100853 if (strcmp(cancel_type, "update-procedure") == 0)
854 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
855 else
856 subscr->sgsn_data->error_cause = GMM_CAUSE_IMPL_DETACHED;
857
Jacob Erlbeck37139e52015-01-23 13:52:55 +0100858 gprs_subscr_cancel(subscr);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100859 gprs_subscr_put(subscr);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100860
861 return CMD_SUCCESS;
862}
863
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100864DEFUN(update_subscr_create, update_subscr_create_cmd,
865 UPDATE_SUBSCR_STR "create",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100866 UPDATE_SUBSCR_HELP
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100867 "Create a subscriber entry\n")
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100868{
869 const char *imsi = argv[0];
870
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100871 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100872
873 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100874 if (subscr) {
875 vty_out(vty, "%% subscriber record already exists for %s%s",
876 imsi, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100877 return CMD_WARNING;
878 }
879
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100880 subscr = gprs_subscr_get_or_create(imsi);
881 subscr->keep_in_ram = 1;
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100882 gprs_subscr_put(subscr);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100883
884 return CMD_SUCCESS;
885}
886
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100887DEFUN(update_subscr_destroy, update_subscr_destroy_cmd,
888 UPDATE_SUBSCR_STR "destroy",
889 UPDATE_SUBSCR_HELP
890 "Destroy a subscriber entry\n")
891{
892 const char *imsi = argv[0];
893
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100894 struct gprs_subscr *subscr;
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100895
896 subscr = gprs_subscr_get_by_imsi(imsi);
897 if (!subscr) {
898 vty_out(vty, "%% subscriber record does not exist for %s%s",
899 imsi, VTY_NEWLINE);
900 return CMD_WARNING;
901 }
902
903 subscr->keep_in_ram = 0;
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100904 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100905 gprs_subscr_cancel(subscr);
906 if (subscr->use_count > 1)
907 vty_out(vty, "%% subscriber is still in use%s",
908 VTY_NEWLINE);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100909 gprs_subscr_put(subscr);
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100910
911 return CMD_SUCCESS;
912}
913
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100914#define UL_ERR_STR "system-failure|data-missing|unexpected-data-value|" \
915 "unknown-subscriber|roaming-not-allowed"
916
917#define UL_ERR_HELP \
918 "Force error code SystemFailure\n" \
919 "Force error code DataMissing\n" \
920 "Force error code UnexpectedDataValue\n" \
921 "Force error code UnknownSubscriber\n" \
922 "Force error code RoamingNotAllowed\n"
923
924DEFUN(update_subscr_update_location_result, update_subscr_update_location_result_cmd,
925 UPDATE_SUBSCR_STR "update-location-result (ok|" UL_ERR_STR ")",
926 UPDATE_SUBSCR_HELP
927 "Complete the update location procedure\n"
928 "The update location request succeeded\n"
929 UL_ERR_HELP)
930{
931 const char *imsi = argv[0];
932 const char *ret_code_str = argv[1];
933
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100934 struct gprs_subscr *subscr;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100935
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100936 const struct value_string cause_mapping[] = {
937 { GMM_CAUSE_NET_FAIL, "system-failure" },
938 { GMM_CAUSE_INV_MAND_INFO, "data-missing" },
939 { GMM_CAUSE_PROTO_ERR_UNSPEC, "unexpected-data-value" },
940 { GMM_CAUSE_IMSI_UNKNOWN, "unknown-subscriber" },
941 { GMM_CAUSE_GPRS_NOTALLOWED, "roaming-not-allowed" },
942 { 0, NULL }
943 };
944
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100945 subscr = gprs_subscr_get_by_imsi(imsi);
946 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100947 vty_out(vty, "%% unable to get subscriber record for %s%s",
948 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100949 return CMD_WARNING;
950 }
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100951
952 if (strcmp(ret_code_str, "ok") == 0) {
953 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100954 subscr->authorized = 1;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100955 } else {
956 subscr->sgsn_data->error_cause =
957 get_string_value(cause_mapping, ret_code_str);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100958 subscr->authorized = 0;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100959 }
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100960
961 gprs_subscr_update(subscr);
962
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100963 gprs_subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100964
965 return CMD_SUCCESS;
966}
967
968DEFUN(update_subscr_update_auth_info, update_subscr_update_auth_info_cmd,
969 UPDATE_SUBSCR_STR "update-auth-info",
970 UPDATE_SUBSCR_HELP
971 "Complete the send authentication info procedure\n")
972{
973 const char *imsi = argv[0];
974
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100975 struct gprs_subscr *subscr;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100976
977 subscr = gprs_subscr_get_by_imsi(imsi);
978 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100979 vty_out(vty, "%% unable to get subscriber record for %s%s",
980 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100981 return CMD_WARNING;
982 }
983
984 gprs_subscr_update_auth_info(subscr);
985
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100986 gprs_subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100987
988 return CMD_SUCCESS;
989}
990
Jacob Erlbeck39f040d2014-12-18 12:46:47 +0100991DEFUN(cfg_gsup_remote_ip, cfg_gsup_remote_ip_cmd,
992 "gsup remote-ip A.B.C.D",
993 "GSUP Parameters\n"
994 "Set the IP address of the remote GSUP server\n"
995 "IPv4 Address\n")
996{
997 inet_aton(argv[0], &g_cfg->gsup_server_addr.sin_addr);
998
999 return CMD_SUCCESS;
1000}
1001
1002DEFUN(cfg_gsup_remote_port, cfg_gsup_remote_port_cmd,
1003 "gsup remote-port <0-65535>",
1004 "GSUP Parameters\n"
1005 "Set the TCP port of the remote GSUP server\n"
1006 "Remote TCP port\n")
1007{
1008 g_cfg->gsup_server_port = atoi(argv[0]);
1009
1010 return CMD_SUCCESS;
1011}
1012
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001013DEFUN(cfg_gsup_oap_id, cfg_gsup_oap_id_cmd,
1014 "gsup oap-id <0-65535>",
1015 "GSUP Parameters\n"
1016 "Set the SGSN's OAP client ID\nOAP client ID (0 == disabled)\n")
1017{
1018 /* VTY ensures range */
1019 g_cfg->oap.client_id = (uint16_t)atoi(argv[0]);
1020 return CMD_SUCCESS;
1021}
1022
1023DEFUN(cfg_gsup_oap_k, cfg_gsup_oap_k_cmd,
1024 "gsup oap-k K",
1025 "GSUP Parameters\n"
1026 "Set the OAP shared secret K\nK value (16 byte) hex\n")
1027{
1028 const char *k = argv[0];
1029
1030 g_cfg->oap.secret_k_present = 0;
1031
1032 if ((!k) || (strlen(k) == 0))
1033 goto disable;
1034
1035 int k_len = osmo_hexparse(k,
1036 g_cfg->oap.secret_k,
1037 sizeof(g_cfg->oap.secret_k));
1038 if (k_len != 16) {
1039 vty_out(vty, "%% need exactly 16 octets for oap-k, got %d.%s",
1040 k_len, VTY_NEWLINE);
1041 goto disable;
1042 }
1043
1044 g_cfg->oap.secret_k_present = 1;
1045 return CMD_SUCCESS;
1046
1047disable:
1048 if (g_cfg->oap.client_id > 0) {
1049 vty_out(vty, "%% OAP client ID set, but invalid oap-k value disables OAP.%s",
1050 VTY_NEWLINE);
1051 return CMD_WARNING;
1052 }
1053 return CMD_SUCCESS;
1054}
1055
1056DEFUN(cfg_gsup_oap_opc, cfg_gsup_oap_opc_cmd,
1057 "gsup oap-opc OPC",
1058 "GSUP Parameters\n"
1059 "Set the OAP shared secret OPC\nOPC value (16 byte) hex\n")
1060{
1061 const char *opc = argv[0];
1062
1063 g_cfg->oap.secret_opc_present = 0;
1064
1065 if ((!opc) || (strlen(opc) == 0))
1066 goto disable;
1067
1068 int opc_len = osmo_hexparse(opc,
1069 g_cfg->oap.secret_opc,
1070 sizeof(g_cfg->oap.secret_opc));
1071 if (opc_len != 16) {
1072 vty_out(vty, "%% need exactly 16 octets for oap-opc, got %d.%s",
1073 opc_len, VTY_NEWLINE);
1074 goto disable;
1075 }
1076
1077 g_cfg->oap.secret_opc_present = 1;
1078 return CMD_SUCCESS;
1079
1080disable:
1081 if (g_cfg->oap.client_id > 0) {
1082 vty_out(vty, "%% OAP client ID set, but invalid oap-opc value disables OAP.%s",
1083 VTY_NEWLINE);
1084 return CMD_WARNING;
1085 }
1086 return CMD_SUCCESS;
1087}
1088
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001089DEFUN(cfg_apn_name, cfg_apn_name_cmd,
1090 "access-point-name NAME",
1091 "Configure a global list of allowed APNs\n"
1092 "Add this NAME to the list\n")
1093{
1094 return add_apn_ggsn_mapping(vty, argv[0], "", 0);
1095}
1096
1097DEFUN(cfg_no_apn_name, cfg_no_apn_name_cmd,
1098 "no access-point-name NAME",
1099 NO_STR "Configure a global list of allowed APNs\n"
1100 "Remove entry with NAME\n")
1101{
1102 struct apn_ctx *apn_ctx = sgsn_apn_ctx_by_name(argv[0], "");
1103 if (!apn_ctx)
1104 return CMD_SUCCESS;
1105
1106 sgsn_apn_ctx_free(apn_ctx);
1107 return CMD_SUCCESS;
1108}
1109
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001110DEFUN(cfg_cdr_filename, cfg_cdr_filename_cmd,
1111 "cdr filename NAME",
1112 "CDR\nSet filename\nname\n")
1113{
1114 talloc_free(g_cfg->cdr.filename);
1115 g_cfg->cdr.filename = talloc_strdup(tall_vty_ctx, argv[0]);
1116 return CMD_SUCCESS;
1117}
1118
1119DEFUN(cfg_no_cdr_filename, cfg_no_cdr_filename_cmd,
1120 "no cdr filename",
1121 NO_STR "CDR\nDisable CDR generation\n")
1122{
1123 talloc_free(g_cfg->cdr.filename);
1124 g_cfg->cdr.filename = NULL;
1125 return CMD_SUCCESS;
1126}
1127
1128DEFUN(cfg_cdr_interval, cfg_cdr_interval_cmd,
1129 "cdr interval <1-2147483647>",
1130 "CDR\nPDP periodic log interval\nSeconds\n")
1131{
1132 g_cfg->cdr.interval = atoi(argv[0]);
1133 return CMD_SUCCESS;
1134}
1135
Philippf1f34362016-08-26 17:00:21 +02001136#define COMPRESSION_STR "Configure compression\n"
1137DEFUN(cfg_no_comp_rfc1144, cfg_no_comp_rfc1144_cmd,
1138 "no compression rfc1144",
1139 NO_STR COMPRESSION_STR "disable rfc1144 TCP/IP header compression\n")
1140{
1141 g_cfg->pcomp_rfc1144.active = 0;
1142 g_cfg->pcomp_rfc1144.passive = 0;
1143 return CMD_SUCCESS;
1144}
1145
1146DEFUN(cfg_comp_rfc1144, cfg_comp_rfc1144_cmd,
1147 "compression rfc1144 active slots <1-256>",
1148 COMPRESSION_STR
1149 "RFC1144 Header compresion scheme\n"
1150 "Compression is actively proposed\n"
1151 "Number of compression state slots\n"
1152 "Number of compression state slots\n")
1153{
1154 g_cfg->pcomp_rfc1144.active = 1;
1155 g_cfg->pcomp_rfc1144.passive = 1;
1156 g_cfg->pcomp_rfc1144.s01 = atoi(argv[0]) - 1;
1157 return CMD_SUCCESS;
1158}
1159
1160DEFUN(cfg_comp_rfc1144p, cfg_comp_rfc1144p_cmd,
1161 "compression rfc1144 passive",
1162 COMPRESSION_STR
1163 "RFC1144 Header compresion scheme\n"
1164 "Compression is available on request\n")
1165{
1166 g_cfg->pcomp_rfc1144.active = 0;
1167 g_cfg->pcomp_rfc1144.passive = 1;
1168 return CMD_SUCCESS;
1169}
1170
Philipp73f83d52016-09-02 13:38:01 +02001171DEFUN(cfg_no_comp_v42bis, cfg_no_comp_v42bis_cmd,
1172 "no compression v42bis",
1173 NO_STR COMPRESSION_STR "disable V.42bis data compression\n")
1174{
1175 g_cfg->dcomp_v42bis.active = 0;
1176 g_cfg->dcomp_v42bis.passive = 0;
1177 return CMD_SUCCESS;
1178}
1179
1180DEFUN(cfg_comp_v42bis, cfg_comp_v42bis_cmd,
1181 "compression v42bis active direction (ms|sgsn|both) codewords <512-65535> strlen <6-250>",
1182 COMPRESSION_STR
1183 "V.42bis data compresion scheme\n"
1184 "Compression is actively proposed\n"
1185 "Direction in which the compression shall be active (p0)\n"
1186 "Compress ms->sgsn direction only\n"
1187 "Compress sgsn->ms direction only\n"
1188 "Both directions\n"
1189 "Number of codewords (p1)\n"
1190 "Number of codewords\n"
1191 "Maximum string length (p2)\n" "Maximum string length\n")
1192{
1193 g_cfg->dcomp_v42bis.active = 1;
1194 g_cfg->dcomp_v42bis.passive = 1;
1195
1196 switch (argv[0][0]) {
1197 case 'm':
1198 g_cfg->dcomp_v42bis.p0 = 1;
1199 break;
1200 case 's':
1201 g_cfg->dcomp_v42bis.p0 = 2;
1202 break;
1203 case 'b':
1204 g_cfg->dcomp_v42bis.p0 = 3;
1205 break;
1206 }
1207
1208 g_cfg->dcomp_v42bis.p1 = atoi(argv[1]);
1209 g_cfg->dcomp_v42bis.p2 = atoi(argv[2]);
1210 return CMD_SUCCESS;
1211}
1212
1213DEFUN(cfg_comp_v42bisp, cfg_comp_v42bisp_cmd,
1214 "compression v42bis passive",
1215 COMPRESSION_STR
1216 "V.42bis data compresion scheme\n"
1217 "Compression is available on request\n")
1218{
1219 g_cfg->dcomp_v42bis.active = 0;
1220 g_cfg->dcomp_v42bis.passive = 1;
1221 return CMD_SUCCESS;
1222}
1223
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001224int sgsn_vty_init(struct sgsn_config *cfg)
Harald Welte288be162010-05-01 16:48:27 +02001225{
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001226 g_cfg = cfg;
1227
Harald Welted193cb32010-05-17 22:58:03 +02001228 install_element_ve(&show_sgsn_cmd);
1229 //install_element_ve(&show_mmctx_tlli_cmd);
1230 install_element_ve(&show_mmctx_imsi_cmd);
1231 install_element_ve(&show_mmctx_all_cmd);
1232 install_element_ve(&show_pdpctx_all_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001233 install_element_ve(&show_subscr_cache_cmd);
1234
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01001235 install_element(ENABLE_NODE, &update_subscr_insert_auth_triplet_cmd);
Jacob Erlbeckd9193432015-01-19 14:11:46 +01001236 install_element(ENABLE_NODE, &update_subscr_create_cmd);
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001237 install_element(ENABLE_NODE, &update_subscr_destroy_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001238 install_element(ENABLE_NODE, &update_subscr_cancel_cmd);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001239 install_element(ENABLE_NODE, &update_subscr_update_location_result_cmd);
1240 install_element(ENABLE_NODE, &update_subscr_update_auth_info_cmd);
Harald Welte288be162010-05-01 16:48:27 +02001241
1242 install_element(CONFIG_NODE, &cfg_sgsn_cmd);
1243 install_node(&sgsn_node, config_write_sgsn);
Jacob Erlbeck36722e12013-10-29 09:30:30 +01001244 vty_install_default(SGSN_NODE);
Harald Weltee300d002010-06-02 12:41:34 +02001245 install_element(SGSN_NODE, &cfg_sgsn_bind_addr_cmd);
Harald Welted193cb32010-05-17 22:58:03 +02001246 install_element(SGSN_NODE, &cfg_ggsn_remote_ip_cmd);
1247 //install_element(SGSN_NODE, &cfg_ggsn_remote_port_cmd);
1248 install_element(SGSN_NODE, &cfg_ggsn_gtp_version_cmd);
Harald Welte7f6da482013-03-19 11:00:13 +01001249 install_element(SGSN_NODE, &cfg_imsi_acl_cmd);
Harald Welte3dfb5492013-03-19 11:48:54 +01001250 install_element(SGSN_NODE, &cfg_auth_policy_cmd);
Max93408ae2016-06-28 14:10:16 +02001251 install_element(SGSN_NODE, &cfg_encrypt_cmd);
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001252 install_element(SGSN_NODE, &cfg_gsup_remote_ip_cmd);
1253 install_element(SGSN_NODE, &cfg_gsup_remote_port_cmd);
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001254 install_element(SGSN_NODE, &cfg_gsup_oap_id_cmd);
1255 install_element(SGSN_NODE, &cfg_gsup_oap_k_cmd);
1256 install_element(SGSN_NODE, &cfg_gsup_oap_opc_cmd);
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +01001257 install_element(SGSN_NODE, &cfg_apn_ggsn_cmd);
1258 install_element(SGSN_NODE, &cfg_apn_imsi_ggsn_cmd);
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001259 install_element(SGSN_NODE, &cfg_apn_name_cmd);
1260 install_element(SGSN_NODE, &cfg_no_apn_name_cmd);
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001261 install_element(SGSN_NODE, &cfg_cdr_filename_cmd);
1262 install_element(SGSN_NODE, &cfg_no_cdr_filename_cmd);
1263 install_element(SGSN_NODE, &cfg_cdr_interval_cmd);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001264 install_element(SGSN_NODE, &cfg_ggsn_dynamic_lookup_cmd);
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +08001265 install_element(SGSN_NODE, &cfg_grx_ggsn_cmd);
Harald Welte288be162010-05-01 16:48:27 +02001266
Harald Welte94508822015-08-15 19:08:21 +02001267 install_element(SGSN_NODE, &cfg_sgsn_T3312_cmd);
1268 install_element(SGSN_NODE, &cfg_sgsn_T3322_cmd);
1269 install_element(SGSN_NODE, &cfg_sgsn_T3350_cmd);
1270 install_element(SGSN_NODE, &cfg_sgsn_T3360_cmd);
1271 install_element(SGSN_NODE, &cfg_sgsn_T3370_cmd);
1272 install_element(SGSN_NODE, &cfg_sgsn_T3313_cmd);
1273 install_element(SGSN_NODE, &cfg_sgsn_T3314_cmd);
1274 install_element(SGSN_NODE, &cfg_sgsn_T3316_cmd);
1275 install_element(SGSN_NODE, &cfg_sgsn_T3385_cmd);
1276 install_element(SGSN_NODE, &cfg_sgsn_T3386_cmd);
1277 install_element(SGSN_NODE, &cfg_sgsn_T3395_cmd);
1278 install_element(SGSN_NODE, &cfg_sgsn_T3397_cmd);
1279
Philippf1f34362016-08-26 17:00:21 +02001280 install_element(SGSN_NODE, &cfg_no_comp_rfc1144_cmd);
1281 install_element(SGSN_NODE, &cfg_comp_rfc1144_cmd);
1282 install_element(SGSN_NODE, &cfg_comp_rfc1144p_cmd);
Philipp73f83d52016-09-02 13:38:01 +02001283 install_element(SGSN_NODE, &cfg_no_comp_v42bis_cmd);
1284 install_element(SGSN_NODE, &cfg_comp_v42bis_cmd);
1285 install_element(SGSN_NODE, &cfg_comp_v42bisp_cmd);
Neels Hofmeyr2188a772016-05-20 21:59:55 +02001286
1287#ifdef BUILD_IU
1288 iu_vty_init(SGSN_NODE, &g_cfg->iu.rab_assign_addr_enc);
1289#endif
Harald Welte288be162010-05-01 16:48:27 +02001290 return 0;
1291}
1292
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001293int sgsn_parse_config(const char *config_file)
Harald Welte288be162010-05-01 16:48:27 +02001294{
1295 int rc;
1296
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001297 /* make sure sgsn_vty_init() was called before this */
1298 OSMO_ASSERT(g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +01001299
Harald Welte94508822015-08-15 19:08:21 +02001300 g_cfg->timers.T3312 = GSM0408_T3312_SECS;
1301 g_cfg->timers.T3322 = GSM0408_T3322_SECS;
1302 g_cfg->timers.T3350 = GSM0408_T3350_SECS;
1303 g_cfg->timers.T3360 = GSM0408_T3360_SECS;
1304 g_cfg->timers.T3370 = GSM0408_T3370_SECS;
1305 g_cfg->timers.T3313 = GSM0408_T3313_SECS;
1306 g_cfg->timers.T3314 = GSM0408_T3314_SECS;
1307 g_cfg->timers.T3316 = GSM0408_T3316_SECS;
1308 g_cfg->timers.T3385 = GSM0408_T3385_SECS;
1309 g_cfg->timers.T3386 = GSM0408_T3386_SECS;
1310 g_cfg->timers.T3395 = GSM0408_T3395_SECS;
1311 g_cfg->timers.T3397 = GSM0408_T3397_SECS;
1312
Harald Weltedcccb182010-05-16 20:52:23 +02001313 rc = vty_read_config_file(config_file, NULL);
Harald Welte288be162010-05-01 16:48:27 +02001314 if (rc < 0) {
1315 fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
1316 return rc;
1317 }
1318
Neels Hofmeyr27355c92017-02-24 06:28:31 +01001319 if (g_cfg->auth_policy == SGSN_AUTH_POLICY_REMOTE
1320 && !(g_cfg->gsup_server_addr.sin_addr.s_addr
1321 && g_cfg->gsup_server_port)) {
1322 fprintf(stderr, "Configuration error:"
1323 " 'auth-policy remote' requires both"
1324 " 'gsup remote-ip' and 'gsup remote-port'\n");
1325 return -EINVAL;
1326 }
1327
Harald Welte288be162010-05-01 16:48:27 +02001328 return 0;
1329}