blob: e09a0296b7b07da283e439fae5276e5b6a4238ca [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 Welte288be162010-05-01 16:48:27 +020031
32#include <openbsc/debug.h>
33#include <openbsc/sgsn.h>
Harald Welteea34a4e2012-06-16 14:59:56 +080034#include <osmocom/gprs/gprs_ns.h>
Harald Welted193cb32010-05-17 22:58:03 +020035#include <openbsc/gprs_sgsn.h>
Harald Welte62ab20c2010-05-14 18:59:17 +020036#include <openbsc/vty.h>
Neels Hofmeyreaaee922016-12-08 21:22:58 +010037#include <openbsc/gsup_client.h>
Harald Welte288be162010-05-01 16:48:27 +020038
Harald Welte4b037e42010-05-19 19:45:32 +020039#include <osmocom/vty/command.h>
40#include <osmocom/vty/vty.h>
Pablo Neira Ayuso6110a3f2011-03-28 19:35:00 +020041#include <osmocom/vty/misc.h>
Max93408ae2016-06-28 14:10:16 +020042#include <osmocom/crypt/gprs_cipher.h>
Jacob Erlbeck80547992014-12-19 19:19:46 +010043#include <osmocom/abis/ipa.h>
44
Harald Welted193cb32010-05-17 22:58:03 +020045#include <pdp.h>
46
Harald Welte288be162010-05-01 16:48:27 +020047static struct sgsn_config *g_cfg = NULL;
48
Jacob Erlbeck106f5472014-11-04 10:08:37 +010049const struct value_string sgsn_auth_pol_strs[] = {
50 { SGSN_AUTH_POLICY_OPEN, "accept-all" },
51 { SGSN_AUTH_POLICY_CLOSED, "closed" },
52 { SGSN_AUTH_POLICY_ACL_ONLY, "acl-only" },
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +010053 { SGSN_AUTH_POLICY_REMOTE, "remote" },
Jacob Erlbeck106f5472014-11-04 10:08:37 +010054 { 0, NULL }
55};
56
Harald Welte94508822015-08-15 19:08:21 +020057/* Section 11.2.2 / Table 11.3a GPRS Mobility management timers – MS side */
58#define GSM0408_T3312_SECS (10*60) /* periodic RAU interval, default 54min */
59
60/* Section 11.2.2 / Table 11.4 MM timers netwokr side */
61#define GSM0408_T3322_SECS 6 /* DETACH_REQ -> DETACH_ACC */
62#define GSM0408_T3350_SECS 6 /* waiting for ATT/RAU/TMSI COMPL */
63#define GSM0408_T3360_SECS 6 /* waiting for AUTH/CIPH RESP */
64#define GSM0408_T3370_SECS 6 /* waiting for ID RESP */
65
Alexander Couzens5ba6fb32017-01-31 18:04:27 +010066/* Section 11.2.2 / Table 11.4a MM timers network side */
Harald Welte94508822015-08-15 19:08:21 +020067#define GSM0408_T3313_SECS 30 /* waiting for paging response */
68#define GSM0408_T3314_SECS 44 /* force to STBY on expiry, Ready timer */
69#define GSM0408_T3316_SECS 44
70
71/* Section 11.3 / Table 11.2d Timers of Session Management - network side */
72#define GSM0408_T3385_SECS 8 /* wait for ACT PDP CTX REQ */
73#define GSM0408_T3386_SECS 8 /* wait for MODIFY PDP CTX ACK */
74#define GSM0408_T3395_SECS 8 /* wait for DEACT PDP CTX ACK */
75#define GSM0408_T3397_SECS 8 /* wait for DEACT AA PDP CTX ACK */
76
77#define DECLARE_TIMER(number, doc) \
78 DEFUN(cfg_sgsn_T##number, \
79 cfg_sgsn_T##number##_cmd, \
80 "timer t" #number " <0-65535>", \
81 "Configure GPRS Timers\n" \
Holger Hans Peter Freytherfe60cfb2015-11-02 12:55:07 +010082 doc "\nTimer Value in seconds\n") \
Harald Welte94508822015-08-15 19:08:21 +020083{ \
84 int value = atoi(argv[0]); \
85 \
86 if (value < 0 || value > 65535) { \
87 vty_out(vty, "Timer value %s out of range.%s", \
88 argv[0], VTY_NEWLINE); \
89 return CMD_WARNING; \
90 } \
91 \
92 g_cfg->timers.T##number = value; \
93 return CMD_SUCCESS; \
94}
95
96DECLARE_TIMER(3312, "Periodic RA Update timer (s)")
Neels Hofmeyr65482c92015-10-19 14:37:12 +020097DECLARE_TIMER(3322, "Detach request -> accept timer (s)")
Harald Welte94508822015-08-15 19:08:21 +020098DECLARE_TIMER(3350, "Waiting for ATT/RAU/TMSI_COMPL timer (s)")
99DECLARE_TIMER(3360, "Waiting for AUTH/CIPH response timer (s)")
100DECLARE_TIMER(3370, "Waiting for IDENTITY response timer (s)")
101
102DECLARE_TIMER(3313, "Waiting for paging response timer (s)")
103DECLARE_TIMER(3314, "Force to STANDBY on expiry timer (s)")
Holger Hans Peter Freytherfe60cfb2015-11-02 12:55:07 +0100104DECLARE_TIMER(3316, "AA-Ready timer (s)")
Harald Welte94508822015-08-15 19:08:21 +0200105
106DECLARE_TIMER(3385, "Wait for ACT PDP CTX REQ timer (s)")
107DECLARE_TIMER(3386, "Wait for MODIFY PDP CTX ACK timer (s)")
108DECLARE_TIMER(3395, "Wait for DEACT PDP CTX ACK timer (s)")
109DECLARE_TIMER(3397, "Wait for DEACT AA PDP CTX ACK timer (s)")
110
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100111
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200112#define GSM48_MAX_APN_LEN 102 /* 10.5.6.1 */
Neels Hofmeyr30f7bcb2015-11-08 20:34:47 +0100113/* TODO: consolidate with gprs_apn_to_str(). */
114/** Copy apn to a static buffer, replacing the length octets in apn_enc with '.'
115 * and terminating with a '\0'. Return the static buffer.
116 * len: the length of the encoded APN (which has no terminating zero).
117 */
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200118static char *gprs_apn2str(uint8_t *apn, unsigned int len)
119{
120 static char apnbuf[GSM48_MAX_APN_LEN+1];
Holger Hans Peter Freyther80e03652013-07-04 18:44:16 +0200121 unsigned int i = 0;
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200122
123 if (!apn)
124 return "";
125
126 if (len > sizeof(apnbuf)-1)
127 len = sizeof(apnbuf)-1;
128
129 memcpy(apnbuf, apn, len);
130 apnbuf[len] = '\0';
131
132 /* replace the domain name step sizes with dots */
133 while (i < len) {
134 unsigned int step = apnbuf[i];
135 apnbuf[i] = '.';
136 i += step+1;
137 }
138
139 return apnbuf+1;
140}
141
Holger Hans Peter Freythera2730302014-03-23 18:08:26 +0100142char *gprs_pdpaddr2str(uint8_t *pdpa, uint8_t len)
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200143{
144 static char str[INET6_ADDRSTRLEN + 10];
145
146 if (!pdpa || len < 2)
147 return "none";
148
149 switch (pdpa[0] & 0x0f) {
150 case PDP_TYPE_ORG_IETF:
151 switch (pdpa[1]) {
152 case PDP_TYPE_N_IETF_IPv4:
153 if (len < 2 + 4)
154 break;
155 strcpy(str, "IPv4 ");
156 inet_ntop(AF_INET, pdpa+2, str+5, sizeof(str)-5);
157 return str;
158 case PDP_TYPE_N_IETF_IPv6:
159 if (len < 2 + 8)
160 break;
161 strcpy(str, "IPv6 ");
162 inet_ntop(AF_INET6, pdpa+2, str+5, sizeof(str)-5);
163 return str;
164 default:
165 break;
166 }
167 break;
168 case PDP_TYPE_ORG_ETSI:
169 if (pdpa[1] == PDP_TYPE_N_ETSI_PPP)
170 return "PPP";
171 break;
172 default:
173 break;
174 }
175
176 return "invalid";
177}
178
Harald Welte288be162010-05-01 16:48:27 +0200179static struct cmd_node sgsn_node = {
180 SGSN_NODE,
Harald Welte570ce242012-08-17 13:16:10 +0200181 "%s(config-sgsn)# ",
Harald Welte288be162010-05-01 16:48:27 +0200182 1,
183};
184
185static int config_write_sgsn(struct vty *vty)
186{
Harald Welte77289c22010-05-18 14:32:29 +0200187 struct sgsn_ggsn_ctx *gctx;
Harald Welte7f6da482013-03-19 11:00:13 +0100188 struct imsi_acl_entry *acl;
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100189 struct apn_ctx *actx;
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800190 struct ares_addr_node *server;
Harald Welte288be162010-05-01 16:48:27 +0200191
192 vty_out(vty, "sgsn%s", VTY_NEWLINE);
193
Harald Weltee300d002010-06-02 12:41:34 +0200194 vty_out(vty, " gtp local-ip %s%s",
195 inet_ntoa(g_cfg->gtp_listenaddr.sin_addr), VTY_NEWLINE);
196
Harald Welted193cb32010-05-17 22:58:03 +0200197 llist_for_each_entry(gctx, &sgsn_ggsn_ctxts, list) {
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800198 if (gctx->id == UINT32_MAX)
199 continue;
200
Harald Welteff3bde82010-05-19 15:09:09 +0200201 vty_out(vty, " ggsn %u remote-ip %s%s", gctx->id,
Harald Welted193cb32010-05-17 22:58:03 +0200202 inet_ntoa(gctx->remote_addr), VTY_NEWLINE);
Harald Welteff3bde82010-05-19 15:09:09 +0200203 vty_out(vty, " ggsn %u gtp-version %u%s", gctx->id,
Harald Welted193cb32010-05-17 22:58:03 +0200204 gctx->gtp_version, VTY_NEWLINE);
Harald Welte288be162010-05-01 16:48:27 +0200205 }
206
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800207 if (sgsn->cfg.dynamic_lookup)
208 vty_out(vty, " ggsn dynamic%s", VTY_NEWLINE);
209
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800210 for (server = sgsn->ares_servers; server; server = server->next)
211 vty_out(vty, " grx-dns-add %s%s", inet_ntoa(server->addr.addr4), VTY_NEWLINE);
212
Max93408ae2016-06-28 14:10:16 +0200213 if (g_cfg->cipher != GPRS_ALGO_GEA0)
214 vty_out(vty, " encryption %s%s",
215 get_value_string(gprs_cipher_names, g_cfg->cipher),
216 VTY_NEWLINE);
Jacob Erlbeck39f040d2014-12-18 12:46:47 +0100217 if (g_cfg->gsup_server_addr.sin_addr.s_addr)
218 vty_out(vty, " gsup remote-ip %s%s",
219 inet_ntoa(g_cfg->gsup_server_addr.sin_addr), VTY_NEWLINE);
220 if (g_cfg->gsup_server_port)
221 vty_out(vty, " gsup remote-port %d%s",
222 g_cfg->gsup_server_port, VTY_NEWLINE);
Max176b62a2016-07-04 11:09:07 +0200223 vty_out(vty, " auth-policy %s%s",
224 get_value_string(sgsn_auth_pol_strs, g_cfg->auth_policy),
225 VTY_NEWLINE);
Neels Hofmeyr568a7272015-10-12 11:57:38 +0200226
227 vty_out(vty, " gsup oap-id %d%s",
228 (int)g_cfg->oap.client_id, VTY_NEWLINE);
229 if (g_cfg->oap.secret_k_present != 0)
230 vty_out(vty, " gsup oap-k %s%s",
231 osmo_hexdump_nospc(g_cfg->oap.secret_k, sizeof(g_cfg->oap.secret_k)),
232 VTY_NEWLINE);
233 if (g_cfg->oap.secret_opc_present != 0)
234 vty_out(vty, " gsup oap-opc %s%s",
235 osmo_hexdump_nospc(g_cfg->oap.secret_opc, sizeof(g_cfg->oap.secret_opc)),
236 VTY_NEWLINE);
237
Harald Welte7f6da482013-03-19 11:00:13 +0100238 llist_for_each_entry(acl, &g_cfg->imsi_acl, list)
239 vty_out(vty, " imsi-acl add %s%s", acl->imsi, VTY_NEWLINE);
240
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100241 if (llist_empty(&sgsn_apn_ctxts))
242 vty_out(vty, " ! apn * ggsn 0%s", VTY_NEWLINE);
243 llist_for_each_entry(actx, &sgsn_apn_ctxts, list) {
244 if (strlen(actx->imsi_prefix) > 0)
Holger Hans Peter Freytherb7ae0b32015-05-29 15:11:55 +0200245 vty_out(vty, " apn %s imsi-prefix %s ggsn %u%s",
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100246 actx->name, actx->imsi_prefix, actx->ggsn->id,
247 VTY_NEWLINE);
248 else
Holger Hans Peter Freytherb7ae0b32015-05-29 15:11:55 +0200249 vty_out(vty, " apn %s ggsn %u%s", actx->name,
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100250 actx->ggsn->id, VTY_NEWLINE);
251 }
252
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +0200253 if (g_cfg->cdr.filename)
254 vty_out(vty, " cdr filename %s%s", g_cfg->cdr.filename, VTY_NEWLINE);
255 else
256 vty_out(vty, " no cdr filename%s", VTY_NEWLINE);
257 vty_out(vty, " cdr interval %d%s", g_cfg->cdr.interval, VTY_NEWLINE);
258
Harald Welte94508822015-08-15 19:08:21 +0200259 vty_out(vty, " timer t3312 %d%s", g_cfg->timers.T3312, VTY_NEWLINE);
260 vty_out(vty, " timer t3322 %d%s", g_cfg->timers.T3322, VTY_NEWLINE);
261 vty_out(vty, " timer t3350 %d%s", g_cfg->timers.T3350, VTY_NEWLINE);
262 vty_out(vty, " timer t3360 %d%s", g_cfg->timers.T3360, VTY_NEWLINE);
263 vty_out(vty, " timer t3370 %d%s", g_cfg->timers.T3370, VTY_NEWLINE);
264 vty_out(vty, " timer t3313 %d%s", g_cfg->timers.T3313, VTY_NEWLINE);
265 vty_out(vty, " timer t3314 %d%s", g_cfg->timers.T3314, VTY_NEWLINE);
266 vty_out(vty, " timer t3316 %d%s", g_cfg->timers.T3316, VTY_NEWLINE);
267 vty_out(vty, " timer t3385 %d%s", g_cfg->timers.T3385, VTY_NEWLINE);
268 vty_out(vty, " timer t3386 %d%s", g_cfg->timers.T3386, VTY_NEWLINE);
269 vty_out(vty, " timer t3395 %d%s", g_cfg->timers.T3395, VTY_NEWLINE);
270 vty_out(vty, " timer t3397 %d%s", g_cfg->timers.T3397, VTY_NEWLINE);
271
Philippf1f34362016-08-26 17:00:21 +0200272 if (g_cfg->pcomp_rfc1144.active) {
273 vty_out(vty, " compression rfc1144 active slots %d%s",
274 g_cfg->pcomp_rfc1144.s01 + 1, VTY_NEWLINE);
275 } else if (g_cfg->pcomp_rfc1144.passive) {
276 vty_out(vty, " compression rfc1144 passive%s", VTY_NEWLINE);
277 } else
278 vty_out(vty, " no compression rfc1144%s", VTY_NEWLINE);
279
Philipp73f83d52016-09-02 13:38:01 +0200280 if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 1) {
281 vty_out(vty,
282 " compression v42bis active direction sgsn 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 == 2) {
286 vty_out(vty,
287 " compression v42bis active direction ms 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.active && g_cfg->dcomp_v42bis.p0 == 3) {
291 vty_out(vty,
292 " compression v42bis active direction both codewords %d strlen %d%s",
293 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
294 VTY_NEWLINE);
295 } else if (g_cfg->dcomp_v42bis.passive) {
296 vty_out(vty, " compression v42bis passive%s", VTY_NEWLINE);
297 } else
298 vty_out(vty, " no compression v42bis%s", VTY_NEWLINE);
299
Harald Welte288be162010-05-01 16:48:27 +0200300 return CMD_SUCCESS;
301}
302
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100303#define SGSN_STR "Configure the SGSN\n"
304#define GGSN_STR "Configure the GGSN information\n"
Harald Weltee300d002010-06-02 12:41:34 +0200305
306DEFUN(cfg_sgsn, cfg_sgsn_cmd,
307 "sgsn",
308 SGSN_STR)
Harald Welte288be162010-05-01 16:48:27 +0200309{
310 vty->node = SGSN_NODE;
311 return CMD_SUCCESS;
312}
313
Harald Weltee300d002010-06-02 12:41:34 +0200314DEFUN(cfg_sgsn_bind_addr, cfg_sgsn_bind_addr_cmd,
315 "gtp local-ip A.B.C.D",
316 "GTP Parameters\n"
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100317 "Set the IP address for the local GTP bind\n"
318 "IPv4 Address\n")
Harald Weltee300d002010-06-02 12:41:34 +0200319{
320 inet_aton(argv[0], &g_cfg->gtp_listenaddr.sin_addr);
321
322 return CMD_SUCCESS;
323}
324
Harald Welted193cb32010-05-17 22:58:03 +0200325DEFUN(cfg_ggsn_remote_ip, cfg_ggsn_remote_ip_cmd,
326 "ggsn <0-255> remote-ip A.B.C.D",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100327 GGSN_STR "GGSN Number\n" IP_STR "IPv4 Address\n")
Harald Welted193cb32010-05-17 22:58:03 +0200328{
329 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200330 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welte288be162010-05-01 16:48:27 +0200331
Harald Welted193cb32010-05-17 22:58:03 +0200332 inet_aton(argv[1], &ggc->remote_addr);
Harald Welte288be162010-05-01 16:48:27 +0200333
Harald Welted193cb32010-05-17 22:58:03 +0200334 return CMD_SUCCESS;
335}
336
337#if 0
338DEFUN(cfg_ggsn_remote_port, cfg_ggsn_remote_port_cmd,
339 "ggsn <0-255> remote-port <0-65535>",
340 "")
341{
342 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200343 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welted193cb32010-05-17 22:58:03 +0200344 uint16_t port = atoi(argv[1]);
345
346}
347#endif
348
349DEFUN(cfg_ggsn_gtp_version, cfg_ggsn_gtp_version_cmd,
350 "ggsn <0-255> gtp-version (0|1)",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100351 GGSN_STR "GGSN Number\n" "GTP Version\n"
352 "Version 0\n" "Version 1\n")
Harald Welted193cb32010-05-17 22:58:03 +0200353{
354 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200355 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welted193cb32010-05-17 22:58:03 +0200356
357 if (atoi(argv[1]))
358 ggc->gtp_version = 1;
359 else
360 ggc->gtp_version = 0;
361
362 return CMD_SUCCESS;
363}
364
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800365DEFUN(cfg_ggsn_dynamic_lookup, cfg_ggsn_dynamic_lookup_cmd,
366 "ggsn dynamic",
367 GGSN_STR "Enable dynamic GRX based look-up (requires restart)\n")
368{
369 sgsn->cfg.dynamic_lookup = 1;
370 return CMD_SUCCESS;
371}
372
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800373DEFUN(cfg_grx_ggsn, cfg_grx_ggsn_cmd,
374 "grx-dns-add A.B.C.D",
375 "Add DNS server\nIPv4 address\n")
376{
377 struct ares_addr_node *node = talloc_zero(tall_bsc_ctx, struct ares_addr_node);
378 node->family = AF_INET;
379 inet_aton(argv[0], &node->addr.addr4);
380
381 node->next = sgsn->ares_servers;
382 sgsn->ares_servers = node;
383 return CMD_SUCCESS;
384}
385
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100386#define APN_STR "Configure the information per APN\n"
387#define APN_GW_STR "The APN gateway name optionally prefixed by '*' (wildcard)\n"
388
389static int add_apn_ggsn_mapping(struct vty *vty, const char *apn_str,
390 const char *imsi_prefix, int ggsn_id)
391{
392 struct apn_ctx *actx;
393 struct sgsn_ggsn_ctx *ggsn;
394
395 ggsn = sgsn_ggsn_ctx_by_id(ggsn_id);
396 if (ggsn == NULL) {
397 vty_out(vty, "%% a GGSN with id %d has not been defined%s",
398 ggsn_id, VTY_NEWLINE);
399 return CMD_WARNING;
400 }
401
402 actx = sgsn_apn_ctx_find_alloc(apn_str, imsi_prefix);
403 if (!actx) {
404 vty_out(vty, "%% unable to create APN context for %s/%s%s",
405 apn_str, imsi_prefix, VTY_NEWLINE);
406 return CMD_WARNING;
407 }
408
409 actx->ggsn = ggsn;
410
411 return CMD_SUCCESS;
412}
413
Harald Welted193cb32010-05-17 22:58:03 +0200414DEFUN(cfg_apn_ggsn, cfg_apn_ggsn_cmd,
415 "apn APNAME ggsn <0-255>",
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100416 APN_STR APN_GW_STR
417 "Select the GGSN to use when the APN gateway prefix matches\n"
418 "The GGSN id")
Harald Welted193cb32010-05-17 22:58:03 +0200419{
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100420
421 return add_apn_ggsn_mapping(vty, argv[0], "", atoi(argv[1]));
Harald Welted193cb32010-05-17 22:58:03 +0200422}
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100423
424DEFUN(cfg_apn_imsi_ggsn, cfg_apn_imsi_ggsn_cmd,
425 "apn APNAME imsi-prefix IMSIPRE ggsn <0-255>",
426 APN_STR APN_GW_STR
427 "Restrict rule to a certain IMSI prefix\n"
428 "An IMSI prefix\n"
429 "Select the GGSN to use when APN gateway and IMSI prefix match\n"
430 "The GGSN id")
431{
432
433 return add_apn_ggsn_mapping(vty, argv[0], argv[1], atoi(argv[2]));
434}
Harald Welted193cb32010-05-17 22:58:03 +0200435
436const struct value_string gprs_mm_st_strs[] = {
437 { GMM_DEREGISTERED, "DEREGISTERED" },
438 { GMM_COMMON_PROC_INIT, "COMMON PROCEDURE (INIT)" },
439 { GMM_REGISTERED_NORMAL, "REGISTERED (NORMAL)" },
Harald Weltebffeff82010-06-09 15:50:45 +0200440 { GMM_REGISTERED_SUSPENDED, "REGISTERED (SUSPENDED)" },
Harald Welted193cb32010-05-17 22:58:03 +0200441 { GMM_DEREGISTERED_INIT, "DEREGISTERED (INIT)" },
442 { 0, NULL }
443};
444
Harald Welte471ac7d2016-12-15 19:48:58 +0100445static char *gtp_ntoa(struct ul16_t *ul)
446{
447 if (ul->l == 4) {
448 struct in_addr *ia = (struct in_addr *) ul;
449 return inet_ntoa(*ia);
450 } else {
451 return "UNKNOWN";
452 }
453}
454
Harald Welted193cb32010-05-17 22:58:03 +0200455static void vty_dump_pdp(struct vty *vty, const char *pfx,
456 struct sgsn_pdp_ctx *pdp)
457{
Jacob Erlbeck99985b52014-10-13 10:32:00 +0200458 const char *imsi = pdp->mm ? pdp->mm->imsi : "(detaching)";
Harald Welte471ac7d2016-12-15 19:48:58 +0100459 vty_out(vty, "%sPDP Context IMSI: %s, SAPI: %u, NSAPI: %u, TI: %u%s",
460 pfx, imsi, pdp->sapi, pdp->nsapi, pdp->ti, VTY_NEWLINE);
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200461 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);
Harald Welte471ac7d2016-12-15 19:48:58 +0100467 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 Welteefbdee92010-06-10 00:20:12 +0200476 vty_out_rate_ctr_group(vty, " ", pdp->ctrg);
Harald Welted193cb32010-05-17 22:58:03 +0200477}
478
479static void vty_dump_mmctx(struct vty *vty, const char *pfx,
480 struct sgsn_mm_ctx *mm, int pdp)
481{
482 vty_out(vty, "%sMM Context for IMSI %s, IMEI %s, P-TMSI %08x%s",
483 pfx, mm->imsi, mm->imei, mm->p_tmsi, VTY_NEWLINE);
Holger Hans Peter Freyther8ee13e22015-05-18 10:00:03 +0200484 vty_out(vty, "%s MSISDN: %s, TLLI: %08x%s HLR: %s",
Harald Weltef97ee042015-12-25 19:12:21 +0100485 pfx, mm->msisdn, mm->gb.tlli, mm->hlr, VTY_NEWLINE);
Harald Welted193cb32010-05-17 22:58:03 +0200486 vty_out(vty, "%s MM State: %s, Routeing Area: %u-%u-%u-%u, "
487 "Cell ID: %u%s", pfx,
Alexander Couzens4f8da6d2017-01-31 15:34:26 +0100488 get_value_string(gprs_mm_st_strs, mm->gmm_state),
Harald Welted193cb32010-05-17 22:58:03 +0200489 mm->ra.mcc, mm->ra.mnc, mm->ra.lac, mm->ra.rac,
Harald Weltef97ee042015-12-25 19:12:21 +0100490 mm->gb.cell_id, VTY_NEWLINE);
Harald Welted193cb32010-05-17 22:58:03 +0200491
Harald Welte8acd88f2010-05-18 10:57:45 +0200492 vty_out_rate_ctr_group(vty, " ", mm->ctrg);
493
Harald Welted193cb32010-05-17 22:58:03 +0200494 if (pdp) {
495 struct sgsn_pdp_ctx *pdp;
496
497 llist_for_each_entry(pdp, &mm->pdp_list, list)
498 vty_dump_pdp(vty, " ", pdp);
499 }
500}
501
502DEFUN(show_sgsn, show_sgsn_cmd, "show sgsn",
503 SHOW_STR "Display information about the SGSN")
504{
Jacob Erlbeck80547992014-12-19 19:19:46 +0100505 if (sgsn->gsup_client) {
506 struct ipa_client_conn *link = sgsn->gsup_client->link;
507 vty_out(vty,
508 " Remote authorization: %sconnected to %s:%d via GSUP%s",
509 sgsn->gsup_client->is_connected ? "" : "not ",
510 link->addr, link->port,
511 VTY_NEWLINE);
512 }
Harald Welted193cb32010-05-17 22:58:03 +0200513 /* FIXME: statistics */
514 return CMD_SUCCESS;
515}
516
517#define MMCTX_STR "MM Context\n"
518#define INCLUDE_PDP_STR "Include PDP Context Information\n"
519
520#if 0
521DEFUN(show_mmctx_tlli, show_mmctx_tlli_cmd,
522 "show mm-context tlli HEX [pdp]",
523 SHOW_STR MMCTX_STR "Identify by TLLI\n" "TLLI\n" INCLUDE_PDP_STR)
524{
525 uint32_t tlli;
526 struct sgsn_mm_ctx *mm;
527
528 tlli = strtoul(argv[0], NULL, 16);
529 mm = sgsn_mm_ctx_by_tlli(tlli);
530 if (!mm) {
531 vty_out(vty, "No MM context for TLLI %08x%s",
532 tlli, VTY_NEWLINE);
533 return CMD_WARNING;
534 }
535 vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
536 return CMD_SUCCESS;
537}
538#endif
539
540DEFUN(swow_mmctx_imsi, show_mmctx_imsi_cmd,
541 "show mm-context imsi IMSI [pdp]",
542 SHOW_STR MMCTX_STR "Identify by IMSI\n" "IMSI of the MM Context\n"
543 INCLUDE_PDP_STR)
544{
545 struct sgsn_mm_ctx *mm;
546
547 mm = sgsn_mm_ctx_by_imsi(argv[0]);
548 if (!mm) {
549 vty_out(vty, "No MM context for IMSI %s%s",
550 argv[0], VTY_NEWLINE);
551 return CMD_WARNING;
552 }
553 vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
554 return CMD_SUCCESS;
555}
556
557DEFUN(swow_mmctx_all, show_mmctx_all_cmd,
558 "show mm-context all [pdp]",
559 SHOW_STR MMCTX_STR "All MM Contexts\n" INCLUDE_PDP_STR)
560{
561 struct sgsn_mm_ctx *mm;
562
563 llist_for_each_entry(mm, &sgsn_mm_ctxts, list)
564 vty_dump_mmctx(vty, "", mm, argv[0] ? 1 : 0);
565
566 return CMD_SUCCESS;
567}
568
Harald Welted193cb32010-05-17 22:58:03 +0200569DEFUN(show_pdpctx_all, show_pdpctx_all_cmd,
570 "show pdp-context all",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100571 SHOW_STR "Display information on PDP Context\n" "Show everything\n")
Harald Welted193cb32010-05-17 22:58:03 +0200572{
573 struct sgsn_pdp_ctx *pdp;
574
575 llist_for_each_entry(pdp, &sgsn_pdp_ctxts, g_list)
576 vty_dump_pdp(vty, "", pdp);
577
578 return CMD_SUCCESS;
579}
Harald Welte288be162010-05-01 16:48:27 +0200580
Harald Welte7f6da482013-03-19 11:00:13 +0100581
582DEFUN(imsi_acl, cfg_imsi_acl_cmd,
583 "imsi-acl (add|del) IMSI",
584 "Access Control List of foreign IMSIs\n"
585 "Add IMSI to ACL\n"
586 "Remove IMSI from ACL\n"
587 "IMSI of subscriber\n")
588{
Philipp Maier6ee49d82017-02-28 16:53:07 +0100589 char imsi_sanitized[GSM23003_IMSI_MAX_DIGITS+1];
Harald Welte7f6da482013-03-19 11:00:13 +0100590 const char *op = argv[0];
Philipp Maier6ee49d82017-02-28 16:53:07 +0100591 const char *imsi = imsi_sanitized;
Harald Welte7f6da482013-03-19 11:00:13 +0100592 int rc;
593
Philipp Maier6ee49d82017-02-28 16:53:07 +0100594 /* Sanitize IMSI */
595 if (strlen(argv[1]) > GSM23003_IMSI_MAX_DIGITS) {
596 vty_out(vty, "%% IMSI (%s) too long -- ignored!%s",
597 argv[1], VTY_NEWLINE);
598 return CMD_WARNING;
599 }
600 memset(imsi_sanitized, '0', sizeof(imsi_sanitized));
601 strcpy(imsi_sanitized+GSM23003_IMSI_MAX_DIGITS-strlen(argv[1]),argv[1]);
602
Harald Welte7f6da482013-03-19 11:00:13 +0100603 if (!strcmp(op, "add"))
Jacob Erlbeck3b5d4072014-10-24 15:11:03 +0200604 rc = sgsn_acl_add(imsi, g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +0100605 else
Jacob Erlbeck3b5d4072014-10-24 15:11:03 +0200606 rc = sgsn_acl_del(imsi, g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +0100607
608 if (rc < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100609 vty_out(vty, "%% unable to %s ACL%s", op, VTY_NEWLINE);
Harald Welte7f6da482013-03-19 11:00:13 +0100610 return CMD_WARNING;
611 }
612
613 return CMD_SUCCESS;
614}
615
Max93408ae2016-06-28 14:10:16 +0200616DEFUN(cfg_encrypt, cfg_encrypt_cmd,
617 "encryption (GEA0|GEA1|GEA2|GEA3|GEA4)",
618 "Set encryption algorithm for SGSN\n"
619 "Use GEA0 (no encryption)\n"
620 "Use GEA1\nUse GEA2\nUse GEA3\nUse GEA4\n")
621{
Max93408ae2016-06-28 14:10:16 +0200622 enum gprs_ciph_algo c = get_string_value(gprs_cipher_names, argv[0]);
Max086067f2017-05-02 13:03:28 +0200623 if (c != GPRS_ALGO_GEA0) {
624 if (!gprs_cipher_supported(c)) {
625 vty_out(vty, "%% cipher %s is unsupported in current version%s", argv[0], VTY_NEWLINE);
626 return CMD_WARNING;
627 }
628
629 if (!g_cfg->require_authentication) {
630 vty_out(vty, "%% unable to use encryption %s without authentication: please adjust auth-policy%s",
631 argv[0], VTY_NEWLINE);
632 return CMD_WARNING;
633 }
Max93408ae2016-06-28 14:10:16 +0200634 }
635
636 g_cfg->cipher = c;
637
638 return CMD_SUCCESS;
639}
640
Harald Welte3dfb5492013-03-19 11:48:54 +0100641DEFUN(cfg_auth_policy, cfg_auth_policy_cmd,
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100642 "auth-policy (accept-all|closed|acl-only|remote)",
Harald Welte3dfb5492013-03-19 11:48:54 +0100643 "Autorization Policy of SGSN\n"
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100644 "Accept all IMSIs (DANGEROUS)\n"
645 "Accept only home network subscribers or those in the ACL\n"
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100646 "Accept only subscribers in the ACL\n"
647 "Use remote subscription data only (HLR)\n")
Harald Welte3dfb5492013-03-19 11:48:54 +0100648{
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100649 int val = get_string_value(sgsn_auth_pol_strs, argv[0]);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100650 OSMO_ASSERT(val >= SGSN_AUTH_POLICY_OPEN && val <= SGSN_AUTH_POLICY_REMOTE);
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100651 g_cfg->auth_policy = val;
Jacob Erlbeck9d4f46c2014-12-17 13:20:08 +0100652 g_cfg->require_authentication = (val == SGSN_AUTH_POLICY_REMOTE);
Jacob Erlbeck771573c2014-12-19 18:08:48 +0100653 g_cfg->require_update_location = (val == SGSN_AUTH_POLICY_REMOTE);
Harald Welte3dfb5492013-03-19 11:48:54 +0100654
655 return CMD_SUCCESS;
656}
657
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100658/* Subscriber */
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100659#include <openbsc/gprs_subscriber.h>
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100660
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100661static void subscr_dump_full_vty(struct vty *vty, struct gprs_subscr *gsub, int pending)
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100662{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100663#if 0
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100664 char expire_time[200];
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100665#endif
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100666 struct gsm_auth_tuple *at;
667 int at_idx;
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100668 struct sgsn_subscriber_pdp_data *pdp;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100669
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100670 vty_out(vty, " Authorized: %d%s",
671 gsub->authorized, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100672 vty_out(vty, " LAC: %d/0x%x%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100673 gsub->lac, gsub->lac, VTY_NEWLINE);
674 vty_out(vty, " IMSI: %s%s", gsub->imsi, VTY_NEWLINE);
675 if (gsub->tmsi != GSM_RESERVED_TMSI)
676 vty_out(vty, " TMSI: %08X%s", gsub->tmsi,
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100677 VTY_NEWLINE);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100678 if (gsub->sgsn_data->msisdn_len > 0)
Holger Hans Peter Freytherf7b38262015-04-23 16:58:33 -0400679 vty_out(vty, " MSISDN (BCD): %s%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100680 osmo_hexdump(gsub->sgsn_data->msisdn,
681 gsub->sgsn_data->msisdn_len),
Holger Hans Peter Freytherf7b38262015-04-23 16:58:33 -0400682 VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100683
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100684 if (strlen(gsub->imei) > 0)
685 vty_out(vty, " IMEI: %s%s", gsub->imei, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100686
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100687 for (at_idx = 0; at_idx < ARRAY_SIZE(gsub->sgsn_data->auth_triplets);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100688 at_idx++) {
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100689 at = &gsub->sgsn_data->auth_triplets[at_idx];
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100690 if (at->key_seq == GSM_KEY_SEQ_INVAL)
691 continue;
692
693 vty_out(vty, " A3A8 tuple (used %d times): ",
694 at->use_count);
Harald Welte89837d42016-05-06 23:28:11 +0200695 vty_out(vty, " CKSN: %d, ",
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100696 at->key_seq);
Harald Welte89837d42016-05-06 23:28:11 +0200697 if (at->vec.auth_types & OSMO_AUTH_TYPE_GSM) {
698 vty_out(vty, "RAND: %s, ",
699 osmo_hexdump(at->vec.rand,
700 sizeof(at->vec.rand)));
701 vty_out(vty, "SRES: %s, ",
702 osmo_hexdump(at->vec.sres,
703 sizeof(at->vec.sres)));
704 vty_out(vty, "Kc: %s%s",
705 osmo_hexdump(at->vec.kc,
706 sizeof(at->vec.kc)), VTY_NEWLINE);
707 }
708 if (at->vec.auth_types & OSMO_AUTH_TYPE_UMTS) {
709 vty_out(vty, " AUTN: %s, ",
710 osmo_hexdump(at->vec.autn,
711 sizeof(at->vec.autn)));
712 vty_out(vty, "RES: %s, ",
713 osmo_hexdump(at->vec.res, at->vec.res_len));
714 vty_out(vty, "IK: %s, ",
715 osmo_hexdump(at->vec.ik, sizeof(at->vec.ik)));
716 vty_out(vty, "CK: %s, ",
717 osmo_hexdump(at->vec.ck, sizeof(at->vec.ck)));
718 }
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100719 }
720
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100721 llist_for_each_entry(pdp, &gsub->sgsn_data->pdp_list, list) {
Holger Hans Peter Freytherd05e0692015-04-23 16:59:04 -0400722 vty_out(vty, " PDP info: Id: %d, Type: 0x%04x, APN: '%s' QoS: %s%s",
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100723 pdp->context_id, pdp->pdp_type, pdp->apn_str,
Holger Hans Peter Freytherd05e0692015-04-23 16:59:04 -0400724 osmo_hexdump(pdp->qos_subscribed, pdp->qos_subscribed_len),
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100725 VTY_NEWLINE);
726 }
727
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100728#if 0
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100729 /* print the expiration time of a subscriber */
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100730 if (gsub->expire_lu) {
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100731 strftime(expire_time, sizeof(expire_time),
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100732 "%a, %d %b %Y %T %z", localtime(&gsub->expire_lu));
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100733 expire_time[sizeof(expire_time) - 1] = '\0';
734 vty_out(vty, " Expiration Time: %s%s", expire_time, VTY_NEWLINE);
735 }
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100736#endif
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100737
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100738 if (gsub->flags)
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100739 vty_out(vty, " Flags: %s%s%s%s%s%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100740 gsub->flags & GPRS_SUBSCRIBER_FIRST_CONTACT ?
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100741 "FIRST_CONTACT " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100742 gsub->flags & GPRS_SUBSCRIBER_CANCELLED ?
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100743 "CANCELLED " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100744 gsub->flags & GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING ?
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100745 "UPDATE_LOCATION_PENDING " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100746 gsub->flags & GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING ?
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100747 "AUTH_INFO_PENDING " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100748 gsub->flags & GPRS_SUBSCRIBER_ENABLE_PURGE ?
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100749 "ENABLE_PURGE " : "",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100750 VTY_NEWLINE);
751
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100752 vty_out(vty, " Use count: %u%s", gsub->use_count, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100753}
754
755DEFUN(show_subscr_cache,
756 show_subscr_cache_cmd,
757 "show subscriber cache",
758 SHOW_STR "Show information about subscribers\n"
759 "Display contents of subscriber cache\n")
760{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100761 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100762
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100763 llist_for_each_entry(subscr, gprs_subscribers, entry) {
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100764 vty_out(vty, " Subscriber:%s", VTY_NEWLINE);
765 subscr_dump_full_vty(vty, subscr, 0);
766 }
767
768 return CMD_SUCCESS;
769}
770
771#define UPDATE_SUBSCR_STR "update-subscriber imsi IMSI "
772#define UPDATE_SUBSCR_HELP "Update subscriber list\n" \
773 "Use the IMSI to select the subscriber\n" \
774 "The IMSI\n"
775
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100776#define UPDATE_SUBSCR_INSERT_HELP "Insert data into the subscriber record\n"
777
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100778DEFUN(update_subscr_insert_auth_triplet, update_subscr_insert_auth_triplet_cmd,
779 UPDATE_SUBSCR_STR "insert auth-triplet <1-5> sres SRES rand RAND kc KC",
780 UPDATE_SUBSCR_HELP
781 UPDATE_SUBSCR_INSERT_HELP
782 "Update authentication triplet\n"
783 "Triplet index\n"
784 "Set SRES value\nSRES value (4 byte) in hex\n"
785 "Set RAND value\nRAND value (16 byte) in hex\n"
786 "Set Kc value\nKc value (8 byte) in hex\n")
787{
788 const char *imsi = argv[0];
789 const int cksn = atoi(argv[1]) - 1;
790 const char *sres_str = argv[2];
791 const char *rand_str = argv[3];
792 const char *kc_str = argv[4];
793 struct gsm_auth_tuple at = {0,};
794
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100795 struct gprs_subscr *subscr;
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100796
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100797 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100798 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100799 vty_out(vty, "%% unable get subscriber record for %s%s",
800 imsi, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100801 return CMD_WARNING;
802 }
803
804 OSMO_ASSERT(subscr->sgsn_data);
805
Harald Welte121e9a42016-04-20 13:13:19 +0200806 if (osmo_hexparse(sres_str, &at.vec.sres[0], sizeof(at.vec.sres)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100807 vty_out(vty, "%% invalid SRES value '%s'%s",
808 sres_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100809 goto failed;
810 }
Harald Welte121e9a42016-04-20 13:13:19 +0200811 if (osmo_hexparse(rand_str, &at.vec.rand[0], sizeof(at.vec.rand)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100812 vty_out(vty, "%% invalid RAND value '%s'%s",
813 rand_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100814 goto failed;
815 }
Harald Welte121e9a42016-04-20 13:13:19 +0200816 if (osmo_hexparse(kc_str, &at.vec.kc[0], sizeof(at.vec.kc)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100817 vty_out(vty, "%% invalid Kc value '%s'%s",
818 kc_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100819 goto failed;
820 }
821 at.key_seq = cksn;
822
823 subscr->sgsn_data->auth_triplets[cksn] = at;
824 subscr->sgsn_data->auth_triplets_updated = 1;
825
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100826 gprs_subscr_put(subscr);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100827
828 return CMD_SUCCESS;
829
830failed:
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100831 gprs_subscr_put(subscr);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100832 return CMD_SUCCESS;
833}
834
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100835DEFUN(update_subscr_cancel, update_subscr_cancel_cmd,
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100836 UPDATE_SUBSCR_STR "cancel (update-procedure|subscription-withdraw)",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100837 UPDATE_SUBSCR_HELP
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100838 "Cancel (remove) subscriber record\n"
839 "The MS moved to another SGSN\n"
840 "The subscription is no longer valid\n")
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100841{
842 const char *imsi = argv[0];
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100843 const char *cancel_type = argv[1];
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100844
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100845 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100846
847 subscr = gprs_subscr_get_by_imsi(imsi);
848 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100849 vty_out(vty, "%% no subscriber record for %s%s",
850 imsi, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100851 return CMD_WARNING;
852 }
853
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100854 if (strcmp(cancel_type, "update-procedure") == 0)
855 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
856 else
857 subscr->sgsn_data->error_cause = GMM_CAUSE_IMPL_DETACHED;
858
Jacob Erlbeck37139e52015-01-23 13:52:55 +0100859 gprs_subscr_cancel(subscr);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100860 gprs_subscr_put(subscr);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100861
862 return CMD_SUCCESS;
863}
864
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100865DEFUN(update_subscr_create, update_subscr_create_cmd,
866 UPDATE_SUBSCR_STR "create",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100867 UPDATE_SUBSCR_HELP
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100868 "Create a subscriber entry\n")
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100869{
870 const char *imsi = argv[0];
871
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100872 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100873
874 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100875 if (subscr) {
876 vty_out(vty, "%% subscriber record already exists for %s%s",
877 imsi, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100878 return CMD_WARNING;
879 }
880
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100881 subscr = gprs_subscr_get_or_create(imsi);
882 subscr->keep_in_ram = 1;
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100883 gprs_subscr_put(subscr);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100884
885 return CMD_SUCCESS;
886}
887
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100888DEFUN(update_subscr_destroy, update_subscr_destroy_cmd,
889 UPDATE_SUBSCR_STR "destroy",
890 UPDATE_SUBSCR_HELP
891 "Destroy a subscriber entry\n")
892{
893 const char *imsi = argv[0];
894
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100895 struct gprs_subscr *subscr;
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100896
897 subscr = gprs_subscr_get_by_imsi(imsi);
898 if (!subscr) {
899 vty_out(vty, "%% subscriber record does not exist for %s%s",
900 imsi, VTY_NEWLINE);
901 return CMD_WARNING;
902 }
903
904 subscr->keep_in_ram = 0;
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100905 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100906 gprs_subscr_cancel(subscr);
907 if (subscr->use_count > 1)
908 vty_out(vty, "%% subscriber is still in use%s",
909 VTY_NEWLINE);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100910 gprs_subscr_put(subscr);
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100911
912 return CMD_SUCCESS;
913}
914
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100915#define UL_ERR_STR "system-failure|data-missing|unexpected-data-value|" \
916 "unknown-subscriber|roaming-not-allowed"
917
918#define UL_ERR_HELP \
919 "Force error code SystemFailure\n" \
920 "Force error code DataMissing\n" \
921 "Force error code UnexpectedDataValue\n" \
922 "Force error code UnknownSubscriber\n" \
923 "Force error code RoamingNotAllowed\n"
924
925DEFUN(update_subscr_update_location_result, update_subscr_update_location_result_cmd,
926 UPDATE_SUBSCR_STR "update-location-result (ok|" UL_ERR_STR ")",
927 UPDATE_SUBSCR_HELP
928 "Complete the update location procedure\n"
929 "The update location request succeeded\n"
930 UL_ERR_HELP)
931{
932 const char *imsi = argv[0];
933 const char *ret_code_str = argv[1];
934
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100935 struct gprs_subscr *subscr;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100936
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100937 const struct value_string cause_mapping[] = {
938 { GMM_CAUSE_NET_FAIL, "system-failure" },
939 { GMM_CAUSE_INV_MAND_INFO, "data-missing" },
940 { GMM_CAUSE_PROTO_ERR_UNSPEC, "unexpected-data-value" },
941 { GMM_CAUSE_IMSI_UNKNOWN, "unknown-subscriber" },
942 { GMM_CAUSE_GPRS_NOTALLOWED, "roaming-not-allowed" },
943 { 0, NULL }
944 };
945
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100946 subscr = gprs_subscr_get_by_imsi(imsi);
947 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100948 vty_out(vty, "%% unable to get subscriber record for %s%s",
949 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100950 return CMD_WARNING;
951 }
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100952
953 if (strcmp(ret_code_str, "ok") == 0) {
954 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100955 subscr->authorized = 1;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100956 } else {
957 subscr->sgsn_data->error_cause =
958 get_string_value(cause_mapping, ret_code_str);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100959 subscr->authorized = 0;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100960 }
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100961
962 gprs_subscr_update(subscr);
963
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100964 gprs_subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100965
966 return CMD_SUCCESS;
967}
968
969DEFUN(update_subscr_update_auth_info, update_subscr_update_auth_info_cmd,
970 UPDATE_SUBSCR_STR "update-auth-info",
971 UPDATE_SUBSCR_HELP
972 "Complete the send authentication info procedure\n")
973{
974 const char *imsi = argv[0];
975
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100976 struct gprs_subscr *subscr;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100977
978 subscr = gprs_subscr_get_by_imsi(imsi);
979 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100980 vty_out(vty, "%% unable to get subscriber record for %s%s",
981 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100982 return CMD_WARNING;
983 }
984
985 gprs_subscr_update_auth_info(subscr);
986
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100987 gprs_subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100988
989 return CMD_SUCCESS;
990}
991
Jacob Erlbeck39f040d2014-12-18 12:46:47 +0100992DEFUN(cfg_gsup_remote_ip, cfg_gsup_remote_ip_cmd,
993 "gsup remote-ip A.B.C.D",
994 "GSUP Parameters\n"
995 "Set the IP address of the remote GSUP server\n"
996 "IPv4 Address\n")
997{
998 inet_aton(argv[0], &g_cfg->gsup_server_addr.sin_addr);
999
1000 return CMD_SUCCESS;
1001}
1002
1003DEFUN(cfg_gsup_remote_port, cfg_gsup_remote_port_cmd,
1004 "gsup remote-port <0-65535>",
1005 "GSUP Parameters\n"
1006 "Set the TCP port of the remote GSUP server\n"
1007 "Remote TCP port\n")
1008{
1009 g_cfg->gsup_server_port = atoi(argv[0]);
1010
1011 return CMD_SUCCESS;
1012}
1013
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001014DEFUN(cfg_gsup_oap_id, cfg_gsup_oap_id_cmd,
1015 "gsup oap-id <0-65535>",
1016 "GSUP Parameters\n"
1017 "Set the SGSN's OAP client ID\nOAP client ID (0 == disabled)\n")
1018{
1019 /* VTY ensures range */
1020 g_cfg->oap.client_id = (uint16_t)atoi(argv[0]);
1021 return CMD_SUCCESS;
1022}
1023
1024DEFUN(cfg_gsup_oap_k, cfg_gsup_oap_k_cmd,
1025 "gsup oap-k K",
1026 "GSUP Parameters\n"
1027 "Set the OAP shared secret K\nK value (16 byte) hex\n")
1028{
1029 const char *k = argv[0];
1030
1031 g_cfg->oap.secret_k_present = 0;
1032
1033 if ((!k) || (strlen(k) == 0))
1034 goto disable;
1035
1036 int k_len = osmo_hexparse(k,
1037 g_cfg->oap.secret_k,
1038 sizeof(g_cfg->oap.secret_k));
1039 if (k_len != 16) {
1040 vty_out(vty, "%% need exactly 16 octets for oap-k, got %d.%s",
1041 k_len, VTY_NEWLINE);
1042 goto disable;
1043 }
1044
1045 g_cfg->oap.secret_k_present = 1;
1046 return CMD_SUCCESS;
1047
1048disable:
1049 if (g_cfg->oap.client_id > 0) {
1050 vty_out(vty, "%% OAP client ID set, but invalid oap-k value disables OAP.%s",
1051 VTY_NEWLINE);
1052 return CMD_WARNING;
1053 }
1054 return CMD_SUCCESS;
1055}
1056
1057DEFUN(cfg_gsup_oap_opc, cfg_gsup_oap_opc_cmd,
1058 "gsup oap-opc OPC",
1059 "GSUP Parameters\n"
1060 "Set the OAP shared secret OPC\nOPC value (16 byte) hex\n")
1061{
1062 const char *opc = argv[0];
1063
1064 g_cfg->oap.secret_opc_present = 0;
1065
1066 if ((!opc) || (strlen(opc) == 0))
1067 goto disable;
1068
1069 int opc_len = osmo_hexparse(opc,
1070 g_cfg->oap.secret_opc,
1071 sizeof(g_cfg->oap.secret_opc));
1072 if (opc_len != 16) {
1073 vty_out(vty, "%% need exactly 16 octets for oap-opc, got %d.%s",
1074 opc_len, VTY_NEWLINE);
1075 goto disable;
1076 }
1077
1078 g_cfg->oap.secret_opc_present = 1;
1079 return CMD_SUCCESS;
1080
1081disable:
1082 if (g_cfg->oap.client_id > 0) {
1083 vty_out(vty, "%% OAP client ID set, but invalid oap-opc value disables OAP.%s",
1084 VTY_NEWLINE);
1085 return CMD_WARNING;
1086 }
1087 return CMD_SUCCESS;
1088}
1089
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001090DEFUN(cfg_apn_name, cfg_apn_name_cmd,
1091 "access-point-name NAME",
1092 "Configure a global list of allowed APNs\n"
1093 "Add this NAME to the list\n")
1094{
1095 return add_apn_ggsn_mapping(vty, argv[0], "", 0);
1096}
1097
1098DEFUN(cfg_no_apn_name, cfg_no_apn_name_cmd,
1099 "no access-point-name NAME",
1100 NO_STR "Configure a global list of allowed APNs\n"
1101 "Remove entry with NAME\n")
1102{
1103 struct apn_ctx *apn_ctx = sgsn_apn_ctx_by_name(argv[0], "");
1104 if (!apn_ctx)
1105 return CMD_SUCCESS;
1106
1107 sgsn_apn_ctx_free(apn_ctx);
1108 return CMD_SUCCESS;
1109}
1110
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001111DEFUN(cfg_cdr_filename, cfg_cdr_filename_cmd,
1112 "cdr filename NAME",
1113 "CDR\nSet filename\nname\n")
1114{
1115 talloc_free(g_cfg->cdr.filename);
1116 g_cfg->cdr.filename = talloc_strdup(tall_vty_ctx, argv[0]);
1117 return CMD_SUCCESS;
1118}
1119
1120DEFUN(cfg_no_cdr_filename, cfg_no_cdr_filename_cmd,
1121 "no cdr filename",
1122 NO_STR "CDR\nDisable CDR generation\n")
1123{
1124 talloc_free(g_cfg->cdr.filename);
1125 g_cfg->cdr.filename = NULL;
1126 return CMD_SUCCESS;
1127}
1128
1129DEFUN(cfg_cdr_interval, cfg_cdr_interval_cmd,
1130 "cdr interval <1-2147483647>",
1131 "CDR\nPDP periodic log interval\nSeconds\n")
1132{
1133 g_cfg->cdr.interval = atoi(argv[0]);
1134 return CMD_SUCCESS;
1135}
1136
Philippf1f34362016-08-26 17:00:21 +02001137#define COMPRESSION_STR "Configure compression\n"
1138DEFUN(cfg_no_comp_rfc1144, cfg_no_comp_rfc1144_cmd,
1139 "no compression rfc1144",
1140 NO_STR COMPRESSION_STR "disable rfc1144 TCP/IP header compression\n")
1141{
1142 g_cfg->pcomp_rfc1144.active = 0;
1143 g_cfg->pcomp_rfc1144.passive = 0;
1144 return CMD_SUCCESS;
1145}
1146
1147DEFUN(cfg_comp_rfc1144, cfg_comp_rfc1144_cmd,
1148 "compression rfc1144 active slots <1-256>",
1149 COMPRESSION_STR
1150 "RFC1144 Header compresion scheme\n"
1151 "Compression is actively proposed\n"
1152 "Number of compression state slots\n"
1153 "Number of compression state slots\n")
1154{
1155 g_cfg->pcomp_rfc1144.active = 1;
1156 g_cfg->pcomp_rfc1144.passive = 1;
1157 g_cfg->pcomp_rfc1144.s01 = atoi(argv[0]) - 1;
1158 return CMD_SUCCESS;
1159}
1160
1161DEFUN(cfg_comp_rfc1144p, cfg_comp_rfc1144p_cmd,
1162 "compression rfc1144 passive",
1163 COMPRESSION_STR
1164 "RFC1144 Header compresion scheme\n"
1165 "Compression is available on request\n")
1166{
1167 g_cfg->pcomp_rfc1144.active = 0;
1168 g_cfg->pcomp_rfc1144.passive = 1;
1169 return CMD_SUCCESS;
1170}
1171
Philipp73f83d52016-09-02 13:38:01 +02001172DEFUN(cfg_no_comp_v42bis, cfg_no_comp_v42bis_cmd,
1173 "no compression v42bis",
1174 NO_STR COMPRESSION_STR "disable V.42bis data compression\n")
1175{
1176 g_cfg->dcomp_v42bis.active = 0;
1177 g_cfg->dcomp_v42bis.passive = 0;
1178 return CMD_SUCCESS;
1179}
1180
1181DEFUN(cfg_comp_v42bis, cfg_comp_v42bis_cmd,
1182 "compression v42bis active direction (ms|sgsn|both) codewords <512-65535> strlen <6-250>",
1183 COMPRESSION_STR
1184 "V.42bis data compresion scheme\n"
1185 "Compression is actively proposed\n"
1186 "Direction in which the compression shall be active (p0)\n"
1187 "Compress ms->sgsn direction only\n"
1188 "Compress sgsn->ms direction only\n"
1189 "Both directions\n"
1190 "Number of codewords (p1)\n"
1191 "Number of codewords\n"
1192 "Maximum string length (p2)\n" "Maximum string length\n")
1193{
1194 g_cfg->dcomp_v42bis.active = 1;
1195 g_cfg->dcomp_v42bis.passive = 1;
1196
1197 switch (argv[0][0]) {
1198 case 'm':
1199 g_cfg->dcomp_v42bis.p0 = 1;
1200 break;
1201 case 's':
1202 g_cfg->dcomp_v42bis.p0 = 2;
1203 break;
1204 case 'b':
1205 g_cfg->dcomp_v42bis.p0 = 3;
1206 break;
1207 }
1208
1209 g_cfg->dcomp_v42bis.p1 = atoi(argv[1]);
1210 g_cfg->dcomp_v42bis.p2 = atoi(argv[2]);
1211 return CMD_SUCCESS;
1212}
1213
1214DEFUN(cfg_comp_v42bisp, cfg_comp_v42bisp_cmd,
1215 "compression v42bis passive",
1216 COMPRESSION_STR
1217 "V.42bis data compresion scheme\n"
1218 "Compression is available on request\n")
1219{
1220 g_cfg->dcomp_v42bis.active = 0;
1221 g_cfg->dcomp_v42bis.passive = 1;
1222 return CMD_SUCCESS;
1223}
1224
Harald Welte288be162010-05-01 16:48:27 +02001225int sgsn_vty_init(void)
1226{
Harald Welted193cb32010-05-17 22:58:03 +02001227 install_element_ve(&show_sgsn_cmd);
1228 //install_element_ve(&show_mmctx_tlli_cmd);
1229 install_element_ve(&show_mmctx_imsi_cmd);
1230 install_element_ve(&show_mmctx_all_cmd);
1231 install_element_ve(&show_pdpctx_all_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001232 install_element_ve(&show_subscr_cache_cmd);
1233
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01001234 install_element(ENABLE_NODE, &update_subscr_insert_auth_triplet_cmd);
Jacob Erlbeckd9193432015-01-19 14:11:46 +01001235 install_element(ENABLE_NODE, &update_subscr_create_cmd);
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001236 install_element(ENABLE_NODE, &update_subscr_destroy_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001237 install_element(ENABLE_NODE, &update_subscr_cancel_cmd);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001238 install_element(ENABLE_NODE, &update_subscr_update_location_result_cmd);
1239 install_element(ENABLE_NODE, &update_subscr_update_auth_info_cmd);
Harald Welte288be162010-05-01 16:48:27 +02001240
1241 install_element(CONFIG_NODE, &cfg_sgsn_cmd);
1242 install_node(&sgsn_node, config_write_sgsn);
Jacob Erlbeck36722e12013-10-29 09:30:30 +01001243 vty_install_default(SGSN_NODE);
Harald Weltee300d002010-06-02 12:41:34 +02001244 install_element(SGSN_NODE, &cfg_sgsn_bind_addr_cmd);
Harald Welted193cb32010-05-17 22:58:03 +02001245 install_element(SGSN_NODE, &cfg_ggsn_remote_ip_cmd);
1246 //install_element(SGSN_NODE, &cfg_ggsn_remote_port_cmd);
1247 install_element(SGSN_NODE, &cfg_ggsn_gtp_version_cmd);
Harald Welte7f6da482013-03-19 11:00:13 +01001248 install_element(SGSN_NODE, &cfg_imsi_acl_cmd);
Harald Welte3dfb5492013-03-19 11:48:54 +01001249 install_element(SGSN_NODE, &cfg_auth_policy_cmd);
Max93408ae2016-06-28 14:10:16 +02001250 install_element(SGSN_NODE, &cfg_encrypt_cmd);
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001251 install_element(SGSN_NODE, &cfg_gsup_remote_ip_cmd);
1252 install_element(SGSN_NODE, &cfg_gsup_remote_port_cmd);
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001253 install_element(SGSN_NODE, &cfg_gsup_oap_id_cmd);
1254 install_element(SGSN_NODE, &cfg_gsup_oap_k_cmd);
1255 install_element(SGSN_NODE, &cfg_gsup_oap_opc_cmd);
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +01001256 install_element(SGSN_NODE, &cfg_apn_ggsn_cmd);
1257 install_element(SGSN_NODE, &cfg_apn_imsi_ggsn_cmd);
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001258 install_element(SGSN_NODE, &cfg_apn_name_cmd);
1259 install_element(SGSN_NODE, &cfg_no_apn_name_cmd);
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001260 install_element(SGSN_NODE, &cfg_cdr_filename_cmd);
1261 install_element(SGSN_NODE, &cfg_no_cdr_filename_cmd);
1262 install_element(SGSN_NODE, &cfg_cdr_interval_cmd);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001263 install_element(SGSN_NODE, &cfg_ggsn_dynamic_lookup_cmd);
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +08001264 install_element(SGSN_NODE, &cfg_grx_ggsn_cmd);
Harald Welte288be162010-05-01 16:48:27 +02001265
Harald Welte94508822015-08-15 19:08:21 +02001266 install_element(SGSN_NODE, &cfg_sgsn_T3312_cmd);
1267 install_element(SGSN_NODE, &cfg_sgsn_T3322_cmd);
1268 install_element(SGSN_NODE, &cfg_sgsn_T3350_cmd);
1269 install_element(SGSN_NODE, &cfg_sgsn_T3360_cmd);
1270 install_element(SGSN_NODE, &cfg_sgsn_T3370_cmd);
1271 install_element(SGSN_NODE, &cfg_sgsn_T3313_cmd);
1272 install_element(SGSN_NODE, &cfg_sgsn_T3314_cmd);
1273 install_element(SGSN_NODE, &cfg_sgsn_T3316_cmd);
1274 install_element(SGSN_NODE, &cfg_sgsn_T3385_cmd);
1275 install_element(SGSN_NODE, &cfg_sgsn_T3386_cmd);
1276 install_element(SGSN_NODE, &cfg_sgsn_T3395_cmd);
1277 install_element(SGSN_NODE, &cfg_sgsn_T3397_cmd);
1278
Philippf1f34362016-08-26 17:00:21 +02001279 install_element(SGSN_NODE, &cfg_no_comp_rfc1144_cmd);
1280 install_element(SGSN_NODE, &cfg_comp_rfc1144_cmd);
1281 install_element(SGSN_NODE, &cfg_comp_rfc1144p_cmd);
Philipp73f83d52016-09-02 13:38:01 +02001282 install_element(SGSN_NODE, &cfg_no_comp_v42bis_cmd);
1283 install_element(SGSN_NODE, &cfg_comp_v42bis_cmd);
1284 install_element(SGSN_NODE, &cfg_comp_v42bisp_cmd);
Harald Welte288be162010-05-01 16:48:27 +02001285 return 0;
1286}
1287
1288int sgsn_parse_config(const char *config_file, struct sgsn_config *cfg)
1289{
1290 int rc;
1291
1292 g_cfg = cfg;
Harald Welte7f6da482013-03-19 11:00:13 +01001293
Harald Welte94508822015-08-15 19:08:21 +02001294 g_cfg->timers.T3312 = GSM0408_T3312_SECS;
1295 g_cfg->timers.T3322 = GSM0408_T3322_SECS;
1296 g_cfg->timers.T3350 = GSM0408_T3350_SECS;
1297 g_cfg->timers.T3360 = GSM0408_T3360_SECS;
1298 g_cfg->timers.T3370 = GSM0408_T3370_SECS;
1299 g_cfg->timers.T3313 = GSM0408_T3313_SECS;
1300 g_cfg->timers.T3314 = GSM0408_T3314_SECS;
1301 g_cfg->timers.T3316 = GSM0408_T3316_SECS;
1302 g_cfg->timers.T3385 = GSM0408_T3385_SECS;
1303 g_cfg->timers.T3386 = GSM0408_T3386_SECS;
1304 g_cfg->timers.T3395 = GSM0408_T3395_SECS;
1305 g_cfg->timers.T3397 = GSM0408_T3397_SECS;
1306
Harald Weltedcccb182010-05-16 20:52:23 +02001307 rc = vty_read_config_file(config_file, NULL);
Harald Welte288be162010-05-01 16:48:27 +02001308 if (rc < 0) {
1309 fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
1310 return rc;
1311 }
1312
Neels Hofmeyr27355c92017-02-24 06:28:31 +01001313 if (g_cfg->auth_policy == SGSN_AUTH_POLICY_REMOTE
1314 && !(g_cfg->gsup_server_addr.sin_addr.s_addr
1315 && g_cfg->gsup_server_port)) {
1316 fprintf(stderr, "Configuration error:"
1317 " 'auth-policy remote' requires both"
1318 " 'gsup remote-ip' and 'gsup remote-port'\n");
1319 return -EINVAL;
1320 }
1321
Harald Welte288be162010-05-01 16:48:27 +02001322 return 0;
1323}