blob: ab02d8175dc09a1a7131de8f26b018021ebc66e0 [file] [log] [blame]
Harald Welte288be162010-05-01 16:48:27 +02001/*
Harald Welte89837d42016-05-06 23:28:11 +02002 * (C) 2010-2016 by Harald Welte <laforge@gnumonks.org>
Harald Welte288be162010-05-01 16:48:27 +02003 * (C) 2010 by On-Waves
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02004 * (C) 2015 by Holger Hans Peter Freyther
Harald Welte288be162010-05-01 16:48:27 +02005 * All Rights Reserved
6 *
7 * This program is free software; you can redistribute it and/or modify
Harald Welte9af6ddf2011-01-01 15:25:50 +01008 * it under the terms of the GNU Affero General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
Harald Welte288be162010-05-01 16:48:27 +020010 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Harald Welte9af6ddf2011-01-01 15:25:50 +010015 * GNU Affero General Public License for more details.
Harald Welte288be162010-05-01 16:48:27 +020016 *
Harald Welte9af6ddf2011-01-01 15:25:50 +010017 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
Harald Welte288be162010-05-01 16:48:27 +020019 *
20 */
21
Harald Welte288be162010-05-01 16:48:27 +020022#include <sys/socket.h>
23#include <netinet/in.h>
24#include <arpa/inet.h>
Jacob Erlbeck207f4a52014-11-11 14:01:48 +010025#include <time.h>
Harald Welte288be162010-05-01 16:48:27 +020026
Pablo Neira Ayuso136f4532011-03-22 16:47:59 +010027#include <osmocom/core/talloc.h>
28#include <osmocom/core/utils.h>
29#include <osmocom/core/rate_ctr.h>
Harald Welte53373bc2016-04-20 17:11:43 +020030#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
Harald Welte7e82b742017-08-12 13:43:54 +020031#include <osmocom/gsm/apn.h>
Harald Welte288be162010-05-01 16:48:27 +020032
Neels Hofmeyr396f2e62017-09-04 15:13:25 +020033#include <osmocom/sgsn/debug.h>
34#include <osmocom/sgsn/sgsn.h>
Harald Welteea34a4e2012-06-16 14:59:56 +080035#include <osmocom/gprs/gprs_ns.h>
Neels Hofmeyr396f2e62017-09-04 15:13:25 +020036#include <osmocom/sgsn/gprs_sgsn.h>
37#include <osmocom/sgsn/vty.h>
38#include <osmocom/sgsn/gsup_client.h>
Harald Welte288be162010-05-01 16:48:27 +020039
Harald Welte4b037e42010-05-19 19:45:32 +020040#include <osmocom/vty/command.h>
41#include <osmocom/vty/vty.h>
Pablo Neira Ayuso6110a3f2011-03-28 19:35:00 +020042#include <osmocom/vty/misc.h>
Max93408ae2016-06-28 14:10:16 +020043#include <osmocom/crypt/gprs_cipher.h>
Jacob Erlbeck80547992014-12-19 19:19:46 +010044#include <osmocom/abis/ipa.h>
45
Harald Welted193cb32010-05-17 22:58:03 +020046#include <pdp.h>
Maxbaabc682017-10-20 13:39:57 +020047#include <gtp.h>
Harald Welted193cb32010-05-17 22:58:03 +020048
Neels Hofmeyr2188a772016-05-20 21:59:55 +020049#include "../../bscconfig.h"
50
51#ifdef BUILD_IU
Neels Hofmeyra7a39472017-07-05 15:19:52 +020052#include <osmocom/ranap/iu_client.h>
Neels Hofmeyr2188a772016-05-20 21:59:55 +020053#endif
54
Neels Hofmeyree6cfdc2017-07-13 02:03:50 +020055extern void *tall_bsc_ctx;
56
Harald Welte288be162010-05-01 16:48:27 +020057static struct sgsn_config *g_cfg = NULL;
58
Jacob Erlbeck106f5472014-11-04 10:08:37 +010059const struct value_string sgsn_auth_pol_strs[] = {
60 { SGSN_AUTH_POLICY_OPEN, "accept-all" },
61 { SGSN_AUTH_POLICY_CLOSED, "closed" },
62 { SGSN_AUTH_POLICY_ACL_ONLY, "acl-only" },
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +010063 { SGSN_AUTH_POLICY_REMOTE, "remote" },
Jacob Erlbeck106f5472014-11-04 10:08:37 +010064 { 0, NULL }
65};
66
Harald Welte94508822015-08-15 19:08:21 +020067/* Section 11.2.2 / Table 11.3a GPRS Mobility management timers – MS side */
68#define GSM0408_T3312_SECS (10*60) /* periodic RAU interval, default 54min */
69
70/* Section 11.2.2 / Table 11.4 MM timers netwokr side */
71#define GSM0408_T3322_SECS 6 /* DETACH_REQ -> DETACH_ACC */
72#define GSM0408_T3350_SECS 6 /* waiting for ATT/RAU/TMSI COMPL */
73#define GSM0408_T3360_SECS 6 /* waiting for AUTH/CIPH RESP */
74#define GSM0408_T3370_SECS 6 /* waiting for ID RESP */
75
Alexander Couzens5ba6fb32017-01-31 18:04:27 +010076/* Section 11.2.2 / Table 11.4a MM timers network side */
Harald Welte94508822015-08-15 19:08:21 +020077#define GSM0408_T3313_SECS 30 /* waiting for paging response */
78#define GSM0408_T3314_SECS 44 /* force to STBY on expiry, Ready timer */
79#define GSM0408_T3316_SECS 44
80
81/* Section 11.3 / Table 11.2d Timers of Session Management - network side */
82#define GSM0408_T3385_SECS 8 /* wait for ACT PDP CTX REQ */
83#define GSM0408_T3386_SECS 8 /* wait for MODIFY PDP CTX ACK */
84#define GSM0408_T3395_SECS 8 /* wait for DEACT PDP CTX ACK */
85#define GSM0408_T3397_SECS 8 /* wait for DEACT AA PDP CTX ACK */
86
87#define DECLARE_TIMER(number, doc) \
88 DEFUN(cfg_sgsn_T##number, \
89 cfg_sgsn_T##number##_cmd, \
90 "timer t" #number " <0-65535>", \
91 "Configure GPRS Timers\n" \
Holger Hans Peter Freytherfe60cfb2015-11-02 12:55:07 +010092 doc "\nTimer Value in seconds\n") \
Harald Welte94508822015-08-15 19:08:21 +020093{ \
94 int value = atoi(argv[0]); \
95 \
96 if (value < 0 || value > 65535) { \
97 vty_out(vty, "Timer value %s out of range.%s", \
98 argv[0], VTY_NEWLINE); \
99 return CMD_WARNING; \
100 } \
101 \
102 g_cfg->timers.T##number = value; \
103 return CMD_SUCCESS; \
104}
105
106DECLARE_TIMER(3312, "Periodic RA Update timer (s)")
Neels Hofmeyr65482c92015-10-19 14:37:12 +0200107DECLARE_TIMER(3322, "Detach request -> accept timer (s)")
Harald Welte94508822015-08-15 19:08:21 +0200108DECLARE_TIMER(3350, "Waiting for ATT/RAU/TMSI_COMPL timer (s)")
109DECLARE_TIMER(3360, "Waiting for AUTH/CIPH response timer (s)")
110DECLARE_TIMER(3370, "Waiting for IDENTITY response timer (s)")
111
112DECLARE_TIMER(3313, "Waiting for paging response timer (s)")
113DECLARE_TIMER(3314, "Force to STANDBY on expiry timer (s)")
Holger Hans Peter Freytherfe60cfb2015-11-02 12:55:07 +0100114DECLARE_TIMER(3316, "AA-Ready timer (s)")
Harald Welte94508822015-08-15 19:08:21 +0200115
116DECLARE_TIMER(3385, "Wait for ACT PDP CTX REQ timer (s)")
117DECLARE_TIMER(3386, "Wait for MODIFY PDP CTX ACK timer (s)")
118DECLARE_TIMER(3395, "Wait for DEACT PDP CTX ACK timer (s)")
119DECLARE_TIMER(3397, "Wait for DEACT AA PDP CTX ACK timer (s)")
120
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100121
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200122#define GSM48_MAX_APN_LEN 102 /* 10.5.6.1 */
Neels Hofmeyr30f7bcb2015-11-08 20:34:47 +0100123/** Copy apn to a static buffer, replacing the length octets in apn_enc with '.'
124 * and terminating with a '\0'. Return the static buffer.
125 * len: the length of the encoded APN (which has no terminating zero).
126 */
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200127static char *gprs_apn2str(uint8_t *apn, unsigned int len)
128{
129 static char apnbuf[GSM48_MAX_APN_LEN+1];
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200130
131 if (!apn)
132 return "";
Harald Welte7e82b742017-08-12 13:43:54 +0200133 osmo_apn_to_str(apnbuf, apn, len);
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200134
135 return apnbuf+1;
136}
137
Holger Hans Peter Freythera2730302014-03-23 18:08:26 +0100138char *gprs_pdpaddr2str(uint8_t *pdpa, uint8_t len)
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200139{
140 static char str[INET6_ADDRSTRLEN + 10];
141
142 if (!pdpa || len < 2)
143 return "none";
144
145 switch (pdpa[0] & 0x0f) {
146 case PDP_TYPE_ORG_IETF:
147 switch (pdpa[1]) {
148 case PDP_TYPE_N_IETF_IPv4:
149 if (len < 2 + 4)
150 break;
151 strcpy(str, "IPv4 ");
152 inet_ntop(AF_INET, pdpa+2, str+5, sizeof(str)-5);
153 return str;
154 case PDP_TYPE_N_IETF_IPv6:
155 if (len < 2 + 8)
156 break;
157 strcpy(str, "IPv6 ");
158 inet_ntop(AF_INET6, pdpa+2, str+5, sizeof(str)-5);
159 return str;
160 default:
161 break;
162 }
163 break;
164 case PDP_TYPE_ORG_ETSI:
165 if (pdpa[1] == PDP_TYPE_N_ETSI_PPP)
166 return "PPP";
167 break;
168 default:
169 break;
170 }
171
172 return "invalid";
173}
174
Harald Welte288be162010-05-01 16:48:27 +0200175static struct cmd_node sgsn_node = {
176 SGSN_NODE,
Harald Welte570ce242012-08-17 13:16:10 +0200177 "%s(config-sgsn)# ",
Harald Welte288be162010-05-01 16:48:27 +0200178 1,
179};
180
181static int config_write_sgsn(struct vty *vty)
182{
Harald Welte77289c22010-05-18 14:32:29 +0200183 struct sgsn_ggsn_ctx *gctx;
Harald Welte7f6da482013-03-19 11:00:13 +0100184 struct imsi_acl_entry *acl;
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100185 struct apn_ctx *actx;
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800186 struct ares_addr_node *server;
Harald Welte288be162010-05-01 16:48:27 +0200187
188 vty_out(vty, "sgsn%s", VTY_NEWLINE);
189
Harald Weltee300d002010-06-02 12:41:34 +0200190 vty_out(vty, " gtp local-ip %s%s",
191 inet_ntoa(g_cfg->gtp_listenaddr.sin_addr), VTY_NEWLINE);
192
Harald Welted193cb32010-05-17 22:58:03 +0200193 llist_for_each_entry(gctx, &sgsn_ggsn_ctxts, list) {
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800194 if (gctx->id == UINT32_MAX)
195 continue;
196
Harald Welteff3bde82010-05-19 15:09:09 +0200197 vty_out(vty, " ggsn %u remote-ip %s%s", gctx->id,
Harald Welted193cb32010-05-17 22:58:03 +0200198 inet_ntoa(gctx->remote_addr), VTY_NEWLINE);
Harald Welteff3bde82010-05-19 15:09:09 +0200199 vty_out(vty, " ggsn %u gtp-version %u%s", gctx->id,
Harald Welted193cb32010-05-17 22:58:03 +0200200 gctx->gtp_version, VTY_NEWLINE);
Harald Welte288be162010-05-01 16:48:27 +0200201 }
202
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800203 if (sgsn->cfg.dynamic_lookup)
204 vty_out(vty, " ggsn dynamic%s", VTY_NEWLINE);
205
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800206 for (server = sgsn->ares_servers; server; server = server->next)
207 vty_out(vty, " grx-dns-add %s%s", inet_ntoa(server->addr.addr4), VTY_NEWLINE);
208
Max93408ae2016-06-28 14:10:16 +0200209 if (g_cfg->cipher != GPRS_ALGO_GEA0)
210 vty_out(vty, " encryption %s%s",
211 get_value_string(gprs_cipher_names, g_cfg->cipher),
212 VTY_NEWLINE);
Jacob Erlbeck39f040d2014-12-18 12:46:47 +0100213 if (g_cfg->gsup_server_addr.sin_addr.s_addr)
214 vty_out(vty, " gsup remote-ip %s%s",
215 inet_ntoa(g_cfg->gsup_server_addr.sin_addr), VTY_NEWLINE);
216 if (g_cfg->gsup_server_port)
217 vty_out(vty, " gsup remote-port %d%s",
218 g_cfg->gsup_server_port, VTY_NEWLINE);
Max176b62a2016-07-04 11:09:07 +0200219 vty_out(vty, " auth-policy %s%s",
220 get_value_string(sgsn_auth_pol_strs, g_cfg->auth_policy),
221 VTY_NEWLINE);
Neels Hofmeyr568a7272015-10-12 11:57:38 +0200222
223 vty_out(vty, " gsup oap-id %d%s",
224 (int)g_cfg->oap.client_id, VTY_NEWLINE);
225 if (g_cfg->oap.secret_k_present != 0)
226 vty_out(vty, " gsup oap-k %s%s",
227 osmo_hexdump_nospc(g_cfg->oap.secret_k, sizeof(g_cfg->oap.secret_k)),
228 VTY_NEWLINE);
229 if (g_cfg->oap.secret_opc_present != 0)
230 vty_out(vty, " gsup oap-opc %s%s",
231 osmo_hexdump_nospc(g_cfg->oap.secret_opc, sizeof(g_cfg->oap.secret_opc)),
232 VTY_NEWLINE);
233
Harald Welte7f6da482013-03-19 11:00:13 +0100234 llist_for_each_entry(acl, &g_cfg->imsi_acl, list)
235 vty_out(vty, " imsi-acl add %s%s", acl->imsi, VTY_NEWLINE);
236
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100237 if (llist_empty(&sgsn_apn_ctxts))
238 vty_out(vty, " ! apn * ggsn 0%s", VTY_NEWLINE);
239 llist_for_each_entry(actx, &sgsn_apn_ctxts, list) {
240 if (strlen(actx->imsi_prefix) > 0)
Holger Hans Peter Freytherb7ae0b32015-05-29 15:11:55 +0200241 vty_out(vty, " apn %s imsi-prefix %s ggsn %u%s",
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100242 actx->name, actx->imsi_prefix, actx->ggsn->id,
243 VTY_NEWLINE);
244 else
Holger Hans Peter Freytherb7ae0b32015-05-29 15:11:55 +0200245 vty_out(vty, " apn %s ggsn %u%s", actx->name,
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100246 actx->ggsn->id, VTY_NEWLINE);
247 }
248
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +0200249 if (g_cfg->cdr.filename)
250 vty_out(vty, " cdr filename %s%s", g_cfg->cdr.filename, VTY_NEWLINE);
251 else
252 vty_out(vty, " no cdr filename%s", VTY_NEWLINE);
253 vty_out(vty, " cdr interval %d%s", g_cfg->cdr.interval, VTY_NEWLINE);
254
Harald Welte94508822015-08-15 19:08:21 +0200255 vty_out(vty, " timer t3312 %d%s", g_cfg->timers.T3312, VTY_NEWLINE);
256 vty_out(vty, " timer t3322 %d%s", g_cfg->timers.T3322, VTY_NEWLINE);
257 vty_out(vty, " timer t3350 %d%s", g_cfg->timers.T3350, VTY_NEWLINE);
258 vty_out(vty, " timer t3360 %d%s", g_cfg->timers.T3360, VTY_NEWLINE);
259 vty_out(vty, " timer t3370 %d%s", g_cfg->timers.T3370, VTY_NEWLINE);
260 vty_out(vty, " timer t3313 %d%s", g_cfg->timers.T3313, VTY_NEWLINE);
261 vty_out(vty, " timer t3314 %d%s", g_cfg->timers.T3314, VTY_NEWLINE);
262 vty_out(vty, " timer t3316 %d%s", g_cfg->timers.T3316, VTY_NEWLINE);
263 vty_out(vty, " timer t3385 %d%s", g_cfg->timers.T3385, VTY_NEWLINE);
264 vty_out(vty, " timer t3386 %d%s", g_cfg->timers.T3386, VTY_NEWLINE);
265 vty_out(vty, " timer t3395 %d%s", g_cfg->timers.T3395, VTY_NEWLINE);
266 vty_out(vty, " timer t3397 %d%s", g_cfg->timers.T3397, VTY_NEWLINE);
267
Philippf1f34362016-08-26 17:00:21 +0200268 if (g_cfg->pcomp_rfc1144.active) {
269 vty_out(vty, " compression rfc1144 active slots %d%s",
270 g_cfg->pcomp_rfc1144.s01 + 1, VTY_NEWLINE);
271 } else if (g_cfg->pcomp_rfc1144.passive) {
272 vty_out(vty, " compression rfc1144 passive%s", VTY_NEWLINE);
273 } else
274 vty_out(vty, " no compression rfc1144%s", VTY_NEWLINE);
275
Philipp73f83d52016-09-02 13:38:01 +0200276 if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 1) {
277 vty_out(vty,
278 " compression v42bis active direction sgsn codewords %d strlen %d%s",
279 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
280 VTY_NEWLINE);
281 } else if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 2) {
282 vty_out(vty,
283 " compression v42bis active direction ms codewords %d strlen %d%s",
284 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
285 VTY_NEWLINE);
286 } else if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 3) {
287 vty_out(vty,
288 " compression v42bis active direction both codewords %d strlen %d%s",
289 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
290 VTY_NEWLINE);
291 } else if (g_cfg->dcomp_v42bis.passive) {
292 vty_out(vty, " compression v42bis passive%s", VTY_NEWLINE);
293 } else
294 vty_out(vty, " no compression v42bis%s", VTY_NEWLINE);
295
Neels Hofmeyr2188a772016-05-20 21:59:55 +0200296#ifdef BUILD_IU
Neels Hofmeyra7a39472017-07-05 15:19:52 +0200297 ranap_iu_vty_config_write(vty, " ");
Neels Hofmeyr2188a772016-05-20 21:59:55 +0200298#endif
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 Weltedfbd2c82017-08-13 00:56:45 +0200461 if (pdp->lib) {
462 vty_out(vty, "%s APN: %s%s", pfx,
463 gprs_apn2str(pdp->lib->apn_use.v, pdp->lib->apn_use.l),
464 VTY_NEWLINE);
465 vty_out(vty, "%s PDP Address: %s%s", pfx,
466 gprs_pdpaddr2str(pdp->lib->eua.v, pdp->lib->eua.l),
467 VTY_NEWLINE);
468 vty_out(vty, "%s GTP Local Control(%s / TEIC: 0x%08x) ", pfx,
469 gtp_ntoa(&pdp->lib->gsnlc), pdp->lib->teic_own);
470 vty_out(vty, "Data(%s / TEID: 0x%08x)%s",
471 gtp_ntoa(&pdp->lib->gsnlu), pdp->lib->teid_own, VTY_NEWLINE);
472 vty_out(vty, "%s GTP Remote Control(%s / TEIC: 0x%08x) ", pfx,
473 gtp_ntoa(&pdp->lib->gsnrc), pdp->lib->teic_gn);
474 vty_out(vty, "Data(%s / TEID: 0x%08x)%s",
475 gtp_ntoa(&pdp->lib->gsnru), pdp->lib->teid_gn, VTY_NEWLINE);
476 }
Harald Welte471ac7d2016-12-15 19:48:58 +0100477
Harald Welteefbdee92010-06-10 00:20:12 +0200478 vty_out_rate_ctr_group(vty, " ", pdp->ctrg);
Harald Welted193cb32010-05-17 22:58:03 +0200479}
480
481static void vty_dump_mmctx(struct vty *vty, const char *pfx,
482 struct sgsn_mm_ctx *mm, int pdp)
483{
484 vty_out(vty, "%sMM Context for IMSI %s, IMEI %s, P-TMSI %08x%s",
485 pfx, mm->imsi, mm->imei, mm->p_tmsi, VTY_NEWLINE);
Holger Hans Peter Freyther8ee13e22015-05-18 10:00:03 +0200486 vty_out(vty, "%s MSISDN: %s, TLLI: %08x%s HLR: %s",
Harald Weltef97ee042015-12-25 19:12:21 +0100487 pfx, mm->msisdn, mm->gb.tlli, mm->hlr, VTY_NEWLINE);
Harald Welted193cb32010-05-17 22:58:03 +0200488 vty_out(vty, "%s MM State: %s, Routeing Area: %u-%u-%u-%u, "
489 "Cell ID: %u%s", pfx,
Alexander Couzens4f8da6d2017-01-31 15:34:26 +0100490 get_value_string(gprs_mm_st_strs, mm->gmm_state),
Harald Welted193cb32010-05-17 22:58:03 +0200491 mm->ra.mcc, mm->ra.mnc, mm->ra.lac, mm->ra.rac,
Harald Weltef97ee042015-12-25 19:12:21 +0100492 mm->gb.cell_id, VTY_NEWLINE);
Harald Welted193cb32010-05-17 22:58:03 +0200493
Harald Welte8acd88f2010-05-18 10:57:45 +0200494 vty_out_rate_ctr_group(vty, " ", mm->ctrg);
495
Harald Welted193cb32010-05-17 22:58:03 +0200496 if (pdp) {
497 struct sgsn_pdp_ctx *pdp;
498
499 llist_for_each_entry(pdp, &mm->pdp_list, list)
500 vty_dump_pdp(vty, " ", pdp);
501 }
502}
503
504DEFUN(show_sgsn, show_sgsn_cmd, "show sgsn",
505 SHOW_STR "Display information about the SGSN")
506{
Jacob Erlbeck80547992014-12-19 19:19:46 +0100507 if (sgsn->gsup_client) {
508 struct ipa_client_conn *link = sgsn->gsup_client->link;
509 vty_out(vty,
510 " Remote authorization: %sconnected to %s:%d via GSUP%s",
511 sgsn->gsup_client->is_connected ? "" : "not ",
512 link->addr, link->port,
513 VTY_NEWLINE);
514 }
Maxbaabc682017-10-20 13:39:57 +0200515 if (sgsn->gsn)
516 vty_out(vty, " GSN: signalling %s, user traffic %s%s",
517 inet_ntoa(sgsn->gsn->gsnc), inet_ntoa(sgsn->gsn->gsnu), VTY_NEWLINE);
518
Harald Welted193cb32010-05-17 22:58:03 +0200519 /* FIXME: statistics */
520 return CMD_SUCCESS;
521}
522
523#define MMCTX_STR "MM Context\n"
524#define INCLUDE_PDP_STR "Include PDP Context Information\n"
525
526#if 0
527DEFUN(show_mmctx_tlli, show_mmctx_tlli_cmd,
528 "show mm-context tlli HEX [pdp]",
529 SHOW_STR MMCTX_STR "Identify by TLLI\n" "TLLI\n" INCLUDE_PDP_STR)
530{
531 uint32_t tlli;
532 struct sgsn_mm_ctx *mm;
533
534 tlli = strtoul(argv[0], NULL, 16);
535 mm = sgsn_mm_ctx_by_tlli(tlli);
536 if (!mm) {
537 vty_out(vty, "No MM context for TLLI %08x%s",
538 tlli, VTY_NEWLINE);
539 return CMD_WARNING;
540 }
541 vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
542 return CMD_SUCCESS;
543}
544#endif
545
546DEFUN(swow_mmctx_imsi, show_mmctx_imsi_cmd,
547 "show mm-context imsi IMSI [pdp]",
548 SHOW_STR MMCTX_STR "Identify by IMSI\n" "IMSI of the MM Context\n"
549 INCLUDE_PDP_STR)
550{
551 struct sgsn_mm_ctx *mm;
552
553 mm = sgsn_mm_ctx_by_imsi(argv[0]);
554 if (!mm) {
555 vty_out(vty, "No MM context for IMSI %s%s",
556 argv[0], VTY_NEWLINE);
557 return CMD_WARNING;
558 }
559 vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
560 return CMD_SUCCESS;
561}
562
563DEFUN(swow_mmctx_all, show_mmctx_all_cmd,
564 "show mm-context all [pdp]",
565 SHOW_STR MMCTX_STR "All MM Contexts\n" INCLUDE_PDP_STR)
566{
567 struct sgsn_mm_ctx *mm;
568
569 llist_for_each_entry(mm, &sgsn_mm_ctxts, list)
570 vty_dump_mmctx(vty, "", mm, argv[0] ? 1 : 0);
571
572 return CMD_SUCCESS;
573}
574
Harald Welted193cb32010-05-17 22:58:03 +0200575DEFUN(show_pdpctx_all, show_pdpctx_all_cmd,
576 "show pdp-context all",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100577 SHOW_STR "Display information on PDP Context\n" "Show everything\n")
Harald Welted193cb32010-05-17 22:58:03 +0200578{
579 struct sgsn_pdp_ctx *pdp;
580
581 llist_for_each_entry(pdp, &sgsn_pdp_ctxts, g_list)
582 vty_dump_pdp(vty, "", pdp);
583
584 return CMD_SUCCESS;
585}
Harald Welte288be162010-05-01 16:48:27 +0200586
Harald Welte7f6da482013-03-19 11:00:13 +0100587
588DEFUN(imsi_acl, cfg_imsi_acl_cmd,
589 "imsi-acl (add|del) IMSI",
590 "Access Control List of foreign IMSIs\n"
591 "Add IMSI to ACL\n"
592 "Remove IMSI from ACL\n"
593 "IMSI of subscriber\n")
594{
Philipp Maier6ee49d82017-02-28 16:53:07 +0100595 char imsi_sanitized[GSM23003_IMSI_MAX_DIGITS+1];
Harald Welte7f6da482013-03-19 11:00:13 +0100596 const char *op = argv[0];
Philipp Maier6ee49d82017-02-28 16:53:07 +0100597 const char *imsi = imsi_sanitized;
Harald Welte7f6da482013-03-19 11:00:13 +0100598 int rc;
599
Philipp Maier6ee49d82017-02-28 16:53:07 +0100600 /* Sanitize IMSI */
601 if (strlen(argv[1]) > GSM23003_IMSI_MAX_DIGITS) {
602 vty_out(vty, "%% IMSI (%s) too long -- ignored!%s",
603 argv[1], VTY_NEWLINE);
604 return CMD_WARNING;
605 }
606 memset(imsi_sanitized, '0', sizeof(imsi_sanitized));
607 strcpy(imsi_sanitized+GSM23003_IMSI_MAX_DIGITS-strlen(argv[1]),argv[1]);
608
Harald Welte7f6da482013-03-19 11:00:13 +0100609 if (!strcmp(op, "add"))
Jacob Erlbeck3b5d4072014-10-24 15:11:03 +0200610 rc = sgsn_acl_add(imsi, g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +0100611 else
Jacob Erlbeck3b5d4072014-10-24 15:11:03 +0200612 rc = sgsn_acl_del(imsi, g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +0100613
614 if (rc < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100615 vty_out(vty, "%% unable to %s ACL%s", op, VTY_NEWLINE);
Harald Welte7f6da482013-03-19 11:00:13 +0100616 return CMD_WARNING;
617 }
618
619 return CMD_SUCCESS;
620}
621
Max93408ae2016-06-28 14:10:16 +0200622DEFUN(cfg_encrypt, cfg_encrypt_cmd,
623 "encryption (GEA0|GEA1|GEA2|GEA3|GEA4)",
624 "Set encryption algorithm for SGSN\n"
625 "Use GEA0 (no encryption)\n"
626 "Use GEA1\nUse GEA2\nUse GEA3\nUse GEA4\n")
627{
Max93408ae2016-06-28 14:10:16 +0200628 enum gprs_ciph_algo c = get_string_value(gprs_cipher_names, argv[0]);
Max086067f2017-05-02 13:03:28 +0200629 if (c != GPRS_ALGO_GEA0) {
630 if (!gprs_cipher_supported(c)) {
631 vty_out(vty, "%% cipher %s is unsupported in current version%s", argv[0], VTY_NEWLINE);
632 return CMD_WARNING;
633 }
634
635 if (!g_cfg->require_authentication) {
636 vty_out(vty, "%% unable to use encryption %s without authentication: please adjust auth-policy%s",
637 argv[0], VTY_NEWLINE);
638 return CMD_WARNING;
639 }
Max93408ae2016-06-28 14:10:16 +0200640 }
641
642 g_cfg->cipher = c;
643
644 return CMD_SUCCESS;
645}
646
Harald Welte3dfb5492013-03-19 11:48:54 +0100647DEFUN(cfg_auth_policy, cfg_auth_policy_cmd,
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100648 "auth-policy (accept-all|closed|acl-only|remote)",
Harald Welte3dfb5492013-03-19 11:48:54 +0100649 "Autorization Policy of SGSN\n"
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100650 "Accept all IMSIs (DANGEROUS)\n"
651 "Accept only home network subscribers or those in the ACL\n"
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100652 "Accept only subscribers in the ACL\n"
653 "Use remote subscription data only (HLR)\n")
Harald Welte3dfb5492013-03-19 11:48:54 +0100654{
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100655 int val = get_string_value(sgsn_auth_pol_strs, argv[0]);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100656 OSMO_ASSERT(val >= SGSN_AUTH_POLICY_OPEN && val <= SGSN_AUTH_POLICY_REMOTE);
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100657 g_cfg->auth_policy = val;
Jacob Erlbeck9d4f46c2014-12-17 13:20:08 +0100658 g_cfg->require_authentication = (val == SGSN_AUTH_POLICY_REMOTE);
Jacob Erlbeck771573c2014-12-19 18:08:48 +0100659 g_cfg->require_update_location = (val == SGSN_AUTH_POLICY_REMOTE);
Harald Welte3dfb5492013-03-19 11:48:54 +0100660
661 return CMD_SUCCESS;
662}
663
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100664/* Subscriber */
Neels Hofmeyr396f2e62017-09-04 15:13:25 +0200665#include <osmocom/sgsn/gprs_subscriber.h>
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100666
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100667static void subscr_dump_full_vty(struct vty *vty, struct gprs_subscr *gsub, int pending)
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100668{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100669#if 0
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100670 char expire_time[200];
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100671#endif
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100672 struct gsm_auth_tuple *at;
673 int at_idx;
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100674 struct sgsn_subscriber_pdp_data *pdp;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100675
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100676 vty_out(vty, " Authorized: %d%s",
677 gsub->authorized, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100678 vty_out(vty, " LAC: %d/0x%x%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100679 gsub->lac, gsub->lac, VTY_NEWLINE);
680 vty_out(vty, " IMSI: %s%s", gsub->imsi, VTY_NEWLINE);
681 if (gsub->tmsi != GSM_RESERVED_TMSI)
682 vty_out(vty, " TMSI: %08X%s", gsub->tmsi,
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100683 VTY_NEWLINE);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100684 if (gsub->sgsn_data->msisdn_len > 0)
Holger Hans Peter Freytherf7b38262015-04-23 16:58:33 -0400685 vty_out(vty, " MSISDN (BCD): %s%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100686 osmo_hexdump(gsub->sgsn_data->msisdn,
687 gsub->sgsn_data->msisdn_len),
Holger Hans Peter Freytherf7b38262015-04-23 16:58:33 -0400688 VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100689
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100690 if (strlen(gsub->imei) > 0)
691 vty_out(vty, " IMEI: %s%s", gsub->imei, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100692
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100693 for (at_idx = 0; at_idx < ARRAY_SIZE(gsub->sgsn_data->auth_triplets);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100694 at_idx++) {
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100695 at = &gsub->sgsn_data->auth_triplets[at_idx];
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100696 if (at->key_seq == GSM_KEY_SEQ_INVAL)
697 continue;
698
699 vty_out(vty, " A3A8 tuple (used %d times): ",
700 at->use_count);
Harald Welte89837d42016-05-06 23:28:11 +0200701 vty_out(vty, " CKSN: %d, ",
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100702 at->key_seq);
Harald Welte89837d42016-05-06 23:28:11 +0200703 if (at->vec.auth_types & OSMO_AUTH_TYPE_GSM) {
704 vty_out(vty, "RAND: %s, ",
705 osmo_hexdump(at->vec.rand,
706 sizeof(at->vec.rand)));
707 vty_out(vty, "SRES: %s, ",
708 osmo_hexdump(at->vec.sres,
709 sizeof(at->vec.sres)));
710 vty_out(vty, "Kc: %s%s",
711 osmo_hexdump(at->vec.kc,
712 sizeof(at->vec.kc)), VTY_NEWLINE);
713 }
714 if (at->vec.auth_types & OSMO_AUTH_TYPE_UMTS) {
715 vty_out(vty, " AUTN: %s, ",
716 osmo_hexdump(at->vec.autn,
717 sizeof(at->vec.autn)));
718 vty_out(vty, "RES: %s, ",
719 osmo_hexdump(at->vec.res, at->vec.res_len));
720 vty_out(vty, "IK: %s, ",
721 osmo_hexdump(at->vec.ik, sizeof(at->vec.ik)));
722 vty_out(vty, "CK: %s, ",
723 osmo_hexdump(at->vec.ck, sizeof(at->vec.ck)));
724 }
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100725 }
726
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100727 llist_for_each_entry(pdp, &gsub->sgsn_data->pdp_list, list) {
Holger Hans Peter Freytherd05e0692015-04-23 16:59:04 -0400728 vty_out(vty, " PDP info: Id: %d, Type: 0x%04x, APN: '%s' QoS: %s%s",
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100729 pdp->context_id, pdp->pdp_type, pdp->apn_str,
Holger Hans Peter Freytherd05e0692015-04-23 16:59:04 -0400730 osmo_hexdump(pdp->qos_subscribed, pdp->qos_subscribed_len),
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100731 VTY_NEWLINE);
732 }
733
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100734#if 0
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100735 /* print the expiration time of a subscriber */
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100736 if (gsub->expire_lu) {
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100737 strftime(expire_time, sizeof(expire_time),
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100738 "%a, %d %b %Y %T %z", localtime(&gsub->expire_lu));
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100739 expire_time[sizeof(expire_time) - 1] = '\0';
740 vty_out(vty, " Expiration Time: %s%s", expire_time, VTY_NEWLINE);
741 }
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100742#endif
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100743
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100744 if (gsub->flags)
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100745 vty_out(vty, " Flags: %s%s%s%s%s%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100746 gsub->flags & GPRS_SUBSCRIBER_FIRST_CONTACT ?
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100747 "FIRST_CONTACT " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100748 gsub->flags & GPRS_SUBSCRIBER_CANCELLED ?
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100749 "CANCELLED " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100750 gsub->flags & GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING ?
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100751 "UPDATE_LOCATION_PENDING " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100752 gsub->flags & GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING ?
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100753 "AUTH_INFO_PENDING " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100754 gsub->flags & GPRS_SUBSCRIBER_ENABLE_PURGE ?
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100755 "ENABLE_PURGE " : "",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100756 VTY_NEWLINE);
757
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100758 vty_out(vty, " Use count: %u%s", gsub->use_count, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100759}
760
761DEFUN(show_subscr_cache,
762 show_subscr_cache_cmd,
763 "show subscriber cache",
764 SHOW_STR "Show information about subscribers\n"
765 "Display contents of subscriber cache\n")
766{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100767 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100768
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100769 llist_for_each_entry(subscr, gprs_subscribers, entry) {
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100770 vty_out(vty, " Subscriber:%s", VTY_NEWLINE);
771 subscr_dump_full_vty(vty, subscr, 0);
772 }
773
774 return CMD_SUCCESS;
775}
776
777#define UPDATE_SUBSCR_STR "update-subscriber imsi IMSI "
778#define UPDATE_SUBSCR_HELP "Update subscriber list\n" \
779 "Use the IMSI to select the subscriber\n" \
780 "The IMSI\n"
781
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100782#define UPDATE_SUBSCR_INSERT_HELP "Insert data into the subscriber record\n"
783
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100784DEFUN(update_subscr_insert_auth_triplet, update_subscr_insert_auth_triplet_cmd,
785 UPDATE_SUBSCR_STR "insert auth-triplet <1-5> sres SRES rand RAND kc KC",
786 UPDATE_SUBSCR_HELP
787 UPDATE_SUBSCR_INSERT_HELP
788 "Update authentication triplet\n"
789 "Triplet index\n"
790 "Set SRES value\nSRES value (4 byte) in hex\n"
791 "Set RAND value\nRAND value (16 byte) in hex\n"
792 "Set Kc value\nKc value (8 byte) in hex\n")
793{
794 const char *imsi = argv[0];
795 const int cksn = atoi(argv[1]) - 1;
796 const char *sres_str = argv[2];
797 const char *rand_str = argv[3];
798 const char *kc_str = argv[4];
799 struct gsm_auth_tuple at = {0,};
800
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100801 struct gprs_subscr *subscr;
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100802
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100803 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100804 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100805 vty_out(vty, "%% unable get subscriber record for %s%s",
806 imsi, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100807 return CMD_WARNING;
808 }
809
810 OSMO_ASSERT(subscr->sgsn_data);
811
Harald Welte121e9a42016-04-20 13:13:19 +0200812 if (osmo_hexparse(sres_str, &at.vec.sres[0], sizeof(at.vec.sres)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100813 vty_out(vty, "%% invalid SRES value '%s'%s",
814 sres_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100815 goto failed;
816 }
Harald Welte121e9a42016-04-20 13:13:19 +0200817 if (osmo_hexparse(rand_str, &at.vec.rand[0], sizeof(at.vec.rand)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100818 vty_out(vty, "%% invalid RAND value '%s'%s",
819 rand_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100820 goto failed;
821 }
Harald Welte121e9a42016-04-20 13:13:19 +0200822 if (osmo_hexparse(kc_str, &at.vec.kc[0], sizeof(at.vec.kc)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100823 vty_out(vty, "%% invalid Kc value '%s'%s",
824 kc_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100825 goto failed;
826 }
827 at.key_seq = cksn;
828
829 subscr->sgsn_data->auth_triplets[cksn] = at;
830 subscr->sgsn_data->auth_triplets_updated = 1;
831
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100832 gprs_subscr_put(subscr);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100833
834 return CMD_SUCCESS;
835
836failed:
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100837 gprs_subscr_put(subscr);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100838 return CMD_SUCCESS;
839}
840
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100841DEFUN(update_subscr_cancel, update_subscr_cancel_cmd,
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100842 UPDATE_SUBSCR_STR "cancel (update-procedure|subscription-withdraw)",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100843 UPDATE_SUBSCR_HELP
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100844 "Cancel (remove) subscriber record\n"
845 "The MS moved to another SGSN\n"
846 "The subscription is no longer valid\n")
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100847{
848 const char *imsi = argv[0];
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100849 const char *cancel_type = argv[1];
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100850
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100851 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100852
853 subscr = gprs_subscr_get_by_imsi(imsi);
854 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100855 vty_out(vty, "%% no subscriber record for %s%s",
856 imsi, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100857 return CMD_WARNING;
858 }
859
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100860 if (strcmp(cancel_type, "update-procedure") == 0)
861 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
862 else
863 subscr->sgsn_data->error_cause = GMM_CAUSE_IMPL_DETACHED;
864
Jacob Erlbeck37139e52015-01-23 13:52:55 +0100865 gprs_subscr_cancel(subscr);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100866 gprs_subscr_put(subscr);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100867
868 return CMD_SUCCESS;
869}
870
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100871DEFUN(update_subscr_create, update_subscr_create_cmd,
872 UPDATE_SUBSCR_STR "create",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100873 UPDATE_SUBSCR_HELP
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100874 "Create a subscriber entry\n")
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100875{
876 const char *imsi = argv[0];
877
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100878 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100879
880 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100881 if (subscr) {
882 vty_out(vty, "%% subscriber record already exists for %s%s",
883 imsi, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100884 return CMD_WARNING;
885 }
886
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100887 subscr = gprs_subscr_get_or_create(imsi);
888 subscr->keep_in_ram = 1;
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100889 gprs_subscr_put(subscr);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100890
891 return CMD_SUCCESS;
892}
893
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100894DEFUN(update_subscr_destroy, update_subscr_destroy_cmd,
895 UPDATE_SUBSCR_STR "destroy",
896 UPDATE_SUBSCR_HELP
897 "Destroy a subscriber entry\n")
898{
899 const char *imsi = argv[0];
900
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100901 struct gprs_subscr *subscr;
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100902
903 subscr = gprs_subscr_get_by_imsi(imsi);
904 if (!subscr) {
905 vty_out(vty, "%% subscriber record does not exist for %s%s",
906 imsi, VTY_NEWLINE);
907 return CMD_WARNING;
908 }
909
910 subscr->keep_in_ram = 0;
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100911 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100912 gprs_subscr_cancel(subscr);
913 if (subscr->use_count > 1)
914 vty_out(vty, "%% subscriber is still in use%s",
915 VTY_NEWLINE);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100916 gprs_subscr_put(subscr);
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100917
918 return CMD_SUCCESS;
919}
920
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100921#define UL_ERR_STR "system-failure|data-missing|unexpected-data-value|" \
922 "unknown-subscriber|roaming-not-allowed"
923
924#define UL_ERR_HELP \
925 "Force error code SystemFailure\n" \
926 "Force error code DataMissing\n" \
927 "Force error code UnexpectedDataValue\n" \
928 "Force error code UnknownSubscriber\n" \
929 "Force error code RoamingNotAllowed\n"
930
931DEFUN(update_subscr_update_location_result, update_subscr_update_location_result_cmd,
932 UPDATE_SUBSCR_STR "update-location-result (ok|" UL_ERR_STR ")",
933 UPDATE_SUBSCR_HELP
934 "Complete the update location procedure\n"
935 "The update location request succeeded\n"
936 UL_ERR_HELP)
937{
938 const char *imsi = argv[0];
939 const char *ret_code_str = argv[1];
940
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100941 struct gprs_subscr *subscr;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100942
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100943 const struct value_string cause_mapping[] = {
944 { GMM_CAUSE_NET_FAIL, "system-failure" },
945 { GMM_CAUSE_INV_MAND_INFO, "data-missing" },
946 { GMM_CAUSE_PROTO_ERR_UNSPEC, "unexpected-data-value" },
947 { GMM_CAUSE_IMSI_UNKNOWN, "unknown-subscriber" },
948 { GMM_CAUSE_GPRS_NOTALLOWED, "roaming-not-allowed" },
949 { 0, NULL }
950 };
951
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100952 subscr = gprs_subscr_get_by_imsi(imsi);
953 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100954 vty_out(vty, "%% unable to get subscriber record for %s%s",
955 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100956 return CMD_WARNING;
957 }
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100958
959 if (strcmp(ret_code_str, "ok") == 0) {
960 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100961 subscr->authorized = 1;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100962 } else {
963 subscr->sgsn_data->error_cause =
964 get_string_value(cause_mapping, ret_code_str);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100965 subscr->authorized = 0;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100966 }
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100967
968 gprs_subscr_update(subscr);
969
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100970 gprs_subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100971
972 return CMD_SUCCESS;
973}
974
975DEFUN(update_subscr_update_auth_info, update_subscr_update_auth_info_cmd,
976 UPDATE_SUBSCR_STR "update-auth-info",
977 UPDATE_SUBSCR_HELP
978 "Complete the send authentication info procedure\n")
979{
980 const char *imsi = argv[0];
981
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100982 struct gprs_subscr *subscr;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100983
984 subscr = gprs_subscr_get_by_imsi(imsi);
985 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100986 vty_out(vty, "%% unable to get subscriber record for %s%s",
987 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100988 return CMD_WARNING;
989 }
990
991 gprs_subscr_update_auth_info(subscr);
992
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100993 gprs_subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100994
995 return CMD_SUCCESS;
996}
997
Jacob Erlbeck39f040d2014-12-18 12:46:47 +0100998DEFUN(cfg_gsup_remote_ip, cfg_gsup_remote_ip_cmd,
999 "gsup remote-ip A.B.C.D",
1000 "GSUP Parameters\n"
1001 "Set the IP address of the remote GSUP server\n"
1002 "IPv4 Address\n")
1003{
1004 inet_aton(argv[0], &g_cfg->gsup_server_addr.sin_addr);
1005
1006 return CMD_SUCCESS;
1007}
1008
1009DEFUN(cfg_gsup_remote_port, cfg_gsup_remote_port_cmd,
1010 "gsup remote-port <0-65535>",
1011 "GSUP Parameters\n"
1012 "Set the TCP port of the remote GSUP server\n"
1013 "Remote TCP port\n")
1014{
1015 g_cfg->gsup_server_port = atoi(argv[0]);
1016
1017 return CMD_SUCCESS;
1018}
1019
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001020DEFUN(cfg_gsup_oap_id, cfg_gsup_oap_id_cmd,
1021 "gsup oap-id <0-65535>",
1022 "GSUP Parameters\n"
1023 "Set the SGSN's OAP client ID\nOAP client ID (0 == disabled)\n")
1024{
1025 /* VTY ensures range */
1026 g_cfg->oap.client_id = (uint16_t)atoi(argv[0]);
1027 return CMD_SUCCESS;
1028}
1029
1030DEFUN(cfg_gsup_oap_k, cfg_gsup_oap_k_cmd,
1031 "gsup oap-k K",
1032 "GSUP Parameters\n"
1033 "Set the OAP shared secret K\nK value (16 byte) hex\n")
1034{
1035 const char *k = argv[0];
1036
1037 g_cfg->oap.secret_k_present = 0;
1038
1039 if ((!k) || (strlen(k) == 0))
1040 goto disable;
1041
1042 int k_len = osmo_hexparse(k,
1043 g_cfg->oap.secret_k,
1044 sizeof(g_cfg->oap.secret_k));
1045 if (k_len != 16) {
1046 vty_out(vty, "%% need exactly 16 octets for oap-k, got %d.%s",
1047 k_len, VTY_NEWLINE);
1048 goto disable;
1049 }
1050
1051 g_cfg->oap.secret_k_present = 1;
1052 return CMD_SUCCESS;
1053
1054disable:
1055 if (g_cfg->oap.client_id > 0) {
1056 vty_out(vty, "%% OAP client ID set, but invalid oap-k value disables OAP.%s",
1057 VTY_NEWLINE);
1058 return CMD_WARNING;
1059 }
1060 return CMD_SUCCESS;
1061}
1062
1063DEFUN(cfg_gsup_oap_opc, cfg_gsup_oap_opc_cmd,
1064 "gsup oap-opc OPC",
1065 "GSUP Parameters\n"
1066 "Set the OAP shared secret OPC\nOPC value (16 byte) hex\n")
1067{
1068 const char *opc = argv[0];
1069
1070 g_cfg->oap.secret_opc_present = 0;
1071
1072 if ((!opc) || (strlen(opc) == 0))
1073 goto disable;
1074
1075 int opc_len = osmo_hexparse(opc,
1076 g_cfg->oap.secret_opc,
1077 sizeof(g_cfg->oap.secret_opc));
1078 if (opc_len != 16) {
1079 vty_out(vty, "%% need exactly 16 octets for oap-opc, got %d.%s",
1080 opc_len, VTY_NEWLINE);
1081 goto disable;
1082 }
1083
1084 g_cfg->oap.secret_opc_present = 1;
1085 return CMD_SUCCESS;
1086
1087disable:
1088 if (g_cfg->oap.client_id > 0) {
1089 vty_out(vty, "%% OAP client ID set, but invalid oap-opc value disables OAP.%s",
1090 VTY_NEWLINE);
1091 return CMD_WARNING;
1092 }
1093 return CMD_SUCCESS;
1094}
1095
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001096DEFUN(cfg_apn_name, cfg_apn_name_cmd,
1097 "access-point-name NAME",
1098 "Configure a global list of allowed APNs\n"
1099 "Add this NAME to the list\n")
1100{
1101 return add_apn_ggsn_mapping(vty, argv[0], "", 0);
1102}
1103
1104DEFUN(cfg_no_apn_name, cfg_no_apn_name_cmd,
1105 "no access-point-name NAME",
1106 NO_STR "Configure a global list of allowed APNs\n"
1107 "Remove entry with NAME\n")
1108{
1109 struct apn_ctx *apn_ctx = sgsn_apn_ctx_by_name(argv[0], "");
1110 if (!apn_ctx)
1111 return CMD_SUCCESS;
1112
1113 sgsn_apn_ctx_free(apn_ctx);
1114 return CMD_SUCCESS;
1115}
1116
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001117DEFUN(cfg_cdr_filename, cfg_cdr_filename_cmd,
1118 "cdr filename NAME",
1119 "CDR\nSet filename\nname\n")
1120{
1121 talloc_free(g_cfg->cdr.filename);
1122 g_cfg->cdr.filename = talloc_strdup(tall_vty_ctx, argv[0]);
1123 return CMD_SUCCESS;
1124}
1125
1126DEFUN(cfg_no_cdr_filename, cfg_no_cdr_filename_cmd,
1127 "no cdr filename",
1128 NO_STR "CDR\nDisable CDR generation\n")
1129{
1130 talloc_free(g_cfg->cdr.filename);
1131 g_cfg->cdr.filename = NULL;
1132 return CMD_SUCCESS;
1133}
1134
1135DEFUN(cfg_cdr_interval, cfg_cdr_interval_cmd,
1136 "cdr interval <1-2147483647>",
1137 "CDR\nPDP periodic log interval\nSeconds\n")
1138{
1139 g_cfg->cdr.interval = atoi(argv[0]);
1140 return CMD_SUCCESS;
1141}
1142
Philippf1f34362016-08-26 17:00:21 +02001143#define COMPRESSION_STR "Configure compression\n"
1144DEFUN(cfg_no_comp_rfc1144, cfg_no_comp_rfc1144_cmd,
1145 "no compression rfc1144",
1146 NO_STR COMPRESSION_STR "disable rfc1144 TCP/IP header compression\n")
1147{
1148 g_cfg->pcomp_rfc1144.active = 0;
1149 g_cfg->pcomp_rfc1144.passive = 0;
1150 return CMD_SUCCESS;
1151}
1152
1153DEFUN(cfg_comp_rfc1144, cfg_comp_rfc1144_cmd,
1154 "compression rfc1144 active slots <1-256>",
1155 COMPRESSION_STR
1156 "RFC1144 Header compresion scheme\n"
1157 "Compression is actively proposed\n"
1158 "Number of compression state slots\n"
1159 "Number of compression state slots\n")
1160{
1161 g_cfg->pcomp_rfc1144.active = 1;
1162 g_cfg->pcomp_rfc1144.passive = 1;
1163 g_cfg->pcomp_rfc1144.s01 = atoi(argv[0]) - 1;
1164 return CMD_SUCCESS;
1165}
1166
1167DEFUN(cfg_comp_rfc1144p, cfg_comp_rfc1144p_cmd,
1168 "compression rfc1144 passive",
1169 COMPRESSION_STR
1170 "RFC1144 Header compresion scheme\n"
1171 "Compression is available on request\n")
1172{
1173 g_cfg->pcomp_rfc1144.active = 0;
1174 g_cfg->pcomp_rfc1144.passive = 1;
1175 return CMD_SUCCESS;
1176}
1177
Philipp73f83d52016-09-02 13:38:01 +02001178DEFUN(cfg_no_comp_v42bis, cfg_no_comp_v42bis_cmd,
1179 "no compression v42bis",
1180 NO_STR COMPRESSION_STR "disable V.42bis data compression\n")
1181{
1182 g_cfg->dcomp_v42bis.active = 0;
1183 g_cfg->dcomp_v42bis.passive = 0;
1184 return CMD_SUCCESS;
1185}
1186
1187DEFUN(cfg_comp_v42bis, cfg_comp_v42bis_cmd,
1188 "compression v42bis active direction (ms|sgsn|both) codewords <512-65535> strlen <6-250>",
1189 COMPRESSION_STR
1190 "V.42bis data compresion scheme\n"
1191 "Compression is actively proposed\n"
1192 "Direction in which the compression shall be active (p0)\n"
1193 "Compress ms->sgsn direction only\n"
1194 "Compress sgsn->ms direction only\n"
1195 "Both directions\n"
1196 "Number of codewords (p1)\n"
1197 "Number of codewords\n"
1198 "Maximum string length (p2)\n" "Maximum string length\n")
1199{
1200 g_cfg->dcomp_v42bis.active = 1;
1201 g_cfg->dcomp_v42bis.passive = 1;
1202
1203 switch (argv[0][0]) {
1204 case 'm':
1205 g_cfg->dcomp_v42bis.p0 = 1;
1206 break;
1207 case 's':
1208 g_cfg->dcomp_v42bis.p0 = 2;
1209 break;
1210 case 'b':
1211 g_cfg->dcomp_v42bis.p0 = 3;
1212 break;
1213 }
1214
1215 g_cfg->dcomp_v42bis.p1 = atoi(argv[1]);
1216 g_cfg->dcomp_v42bis.p2 = atoi(argv[2]);
1217 return CMD_SUCCESS;
1218}
1219
1220DEFUN(cfg_comp_v42bisp, cfg_comp_v42bisp_cmd,
1221 "compression v42bis passive",
1222 COMPRESSION_STR
1223 "V.42bis data compresion scheme\n"
1224 "Compression is available on request\n")
1225{
1226 g_cfg->dcomp_v42bis.active = 0;
1227 g_cfg->dcomp_v42bis.passive = 1;
1228 return CMD_SUCCESS;
1229}
1230
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001231int sgsn_vty_init(struct sgsn_config *cfg)
Harald Welte288be162010-05-01 16:48:27 +02001232{
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001233 g_cfg = cfg;
1234
Harald Welted193cb32010-05-17 22:58:03 +02001235 install_element_ve(&show_sgsn_cmd);
1236 //install_element_ve(&show_mmctx_tlli_cmd);
1237 install_element_ve(&show_mmctx_imsi_cmd);
1238 install_element_ve(&show_mmctx_all_cmd);
1239 install_element_ve(&show_pdpctx_all_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001240 install_element_ve(&show_subscr_cache_cmd);
1241
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01001242 install_element(ENABLE_NODE, &update_subscr_insert_auth_triplet_cmd);
Jacob Erlbeckd9193432015-01-19 14:11:46 +01001243 install_element(ENABLE_NODE, &update_subscr_create_cmd);
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001244 install_element(ENABLE_NODE, &update_subscr_destroy_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001245 install_element(ENABLE_NODE, &update_subscr_cancel_cmd);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001246 install_element(ENABLE_NODE, &update_subscr_update_location_result_cmd);
1247 install_element(ENABLE_NODE, &update_subscr_update_auth_info_cmd);
Harald Welte288be162010-05-01 16:48:27 +02001248
1249 install_element(CONFIG_NODE, &cfg_sgsn_cmd);
1250 install_node(&sgsn_node, config_write_sgsn);
Jacob Erlbeck36722e12013-10-29 09:30:30 +01001251 vty_install_default(SGSN_NODE);
Harald Weltee300d002010-06-02 12:41:34 +02001252 install_element(SGSN_NODE, &cfg_sgsn_bind_addr_cmd);
Harald Welted193cb32010-05-17 22:58:03 +02001253 install_element(SGSN_NODE, &cfg_ggsn_remote_ip_cmd);
1254 //install_element(SGSN_NODE, &cfg_ggsn_remote_port_cmd);
1255 install_element(SGSN_NODE, &cfg_ggsn_gtp_version_cmd);
Harald Welte7f6da482013-03-19 11:00:13 +01001256 install_element(SGSN_NODE, &cfg_imsi_acl_cmd);
Harald Welte3dfb5492013-03-19 11:48:54 +01001257 install_element(SGSN_NODE, &cfg_auth_policy_cmd);
Max93408ae2016-06-28 14:10:16 +02001258 install_element(SGSN_NODE, &cfg_encrypt_cmd);
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001259 install_element(SGSN_NODE, &cfg_gsup_remote_ip_cmd);
1260 install_element(SGSN_NODE, &cfg_gsup_remote_port_cmd);
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001261 install_element(SGSN_NODE, &cfg_gsup_oap_id_cmd);
1262 install_element(SGSN_NODE, &cfg_gsup_oap_k_cmd);
1263 install_element(SGSN_NODE, &cfg_gsup_oap_opc_cmd);
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +01001264 install_element(SGSN_NODE, &cfg_apn_ggsn_cmd);
1265 install_element(SGSN_NODE, &cfg_apn_imsi_ggsn_cmd);
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001266 install_element(SGSN_NODE, &cfg_apn_name_cmd);
1267 install_element(SGSN_NODE, &cfg_no_apn_name_cmd);
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001268 install_element(SGSN_NODE, &cfg_cdr_filename_cmd);
1269 install_element(SGSN_NODE, &cfg_no_cdr_filename_cmd);
1270 install_element(SGSN_NODE, &cfg_cdr_interval_cmd);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001271 install_element(SGSN_NODE, &cfg_ggsn_dynamic_lookup_cmd);
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +08001272 install_element(SGSN_NODE, &cfg_grx_ggsn_cmd);
Harald Welte288be162010-05-01 16:48:27 +02001273
Harald Welte94508822015-08-15 19:08:21 +02001274 install_element(SGSN_NODE, &cfg_sgsn_T3312_cmd);
1275 install_element(SGSN_NODE, &cfg_sgsn_T3322_cmd);
1276 install_element(SGSN_NODE, &cfg_sgsn_T3350_cmd);
1277 install_element(SGSN_NODE, &cfg_sgsn_T3360_cmd);
1278 install_element(SGSN_NODE, &cfg_sgsn_T3370_cmd);
1279 install_element(SGSN_NODE, &cfg_sgsn_T3313_cmd);
1280 install_element(SGSN_NODE, &cfg_sgsn_T3314_cmd);
1281 install_element(SGSN_NODE, &cfg_sgsn_T3316_cmd);
1282 install_element(SGSN_NODE, &cfg_sgsn_T3385_cmd);
1283 install_element(SGSN_NODE, &cfg_sgsn_T3386_cmd);
1284 install_element(SGSN_NODE, &cfg_sgsn_T3395_cmd);
1285 install_element(SGSN_NODE, &cfg_sgsn_T3397_cmd);
1286
Philippf1f34362016-08-26 17:00:21 +02001287 install_element(SGSN_NODE, &cfg_no_comp_rfc1144_cmd);
1288 install_element(SGSN_NODE, &cfg_comp_rfc1144_cmd);
1289 install_element(SGSN_NODE, &cfg_comp_rfc1144p_cmd);
Philipp73f83d52016-09-02 13:38:01 +02001290 install_element(SGSN_NODE, &cfg_no_comp_v42bis_cmd);
1291 install_element(SGSN_NODE, &cfg_comp_v42bis_cmd);
1292 install_element(SGSN_NODE, &cfg_comp_v42bisp_cmd);
Neels Hofmeyr2188a772016-05-20 21:59:55 +02001293
1294#ifdef BUILD_IU
Neels Hofmeyra7a39472017-07-05 15:19:52 +02001295 ranap_iu_vty_init(SGSN_NODE, &g_cfg->iu.rab_assign_addr_enc);
Neels Hofmeyr2188a772016-05-20 21:59:55 +02001296#endif
Harald Welte288be162010-05-01 16:48:27 +02001297 return 0;
1298}
1299
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001300int sgsn_parse_config(const char *config_file)
Harald Welte288be162010-05-01 16:48:27 +02001301{
1302 int rc;
1303
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001304 /* make sure sgsn_vty_init() was called before this */
1305 OSMO_ASSERT(g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +01001306
Harald Welte94508822015-08-15 19:08:21 +02001307 g_cfg->timers.T3312 = GSM0408_T3312_SECS;
1308 g_cfg->timers.T3322 = GSM0408_T3322_SECS;
1309 g_cfg->timers.T3350 = GSM0408_T3350_SECS;
1310 g_cfg->timers.T3360 = GSM0408_T3360_SECS;
1311 g_cfg->timers.T3370 = GSM0408_T3370_SECS;
1312 g_cfg->timers.T3313 = GSM0408_T3313_SECS;
1313 g_cfg->timers.T3314 = GSM0408_T3314_SECS;
1314 g_cfg->timers.T3316 = GSM0408_T3316_SECS;
1315 g_cfg->timers.T3385 = GSM0408_T3385_SECS;
1316 g_cfg->timers.T3386 = GSM0408_T3386_SECS;
1317 g_cfg->timers.T3395 = GSM0408_T3395_SECS;
1318 g_cfg->timers.T3397 = GSM0408_T3397_SECS;
1319
Harald Weltedcccb182010-05-16 20:52:23 +02001320 rc = vty_read_config_file(config_file, NULL);
Harald Welte288be162010-05-01 16:48:27 +02001321 if (rc < 0) {
1322 fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
1323 return rc;
1324 }
1325
Neels Hofmeyr27355c92017-02-24 06:28:31 +01001326 if (g_cfg->auth_policy == SGSN_AUTH_POLICY_REMOTE
1327 && !(g_cfg->gsup_server_addr.sin_addr.s_addr
1328 && g_cfg->gsup_server_port)) {
1329 fprintf(stderr, "Configuration error:"
1330 " 'auth-policy remote' requires both"
1331 " 'gsup remote-ip' and 'gsup remote-port'\n");
1332 return -EINVAL;
1333 }
1334
Harald Welte288be162010-05-01 16:48:27 +02001335 return 0;
1336}