blob: 4a97687e86ee996719930b4e150ac66f806b166d [file] [log] [blame]
Harald Welte55fe0552010-05-01 16:48:27 +02001/*
Harald Weltea0879c12013-03-19 11:00:13 +01002 * (C) 2010-2013 by Harald Welte <laforge@gnumonks.org>
Harald Welte55fe0552010-05-01 16:48:27 +02003 * (C) 2010 by On-Waves
Holger Hans Peter Freyther81283872015-05-06 17:46:08 +02004 * (C) 2015 by Holger Hans Peter Freyther
Harald Welte55fe0552010-05-01 16:48:27 +02005 * All Rights Reserved
6 *
7 * This program is free software; you can redistribute it and/or modify
Harald Welte0e3e88e2011-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 Welte55fe0552010-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 Welte0e3e88e2011-01-01 15:25:50 +010015 * GNU Affero General Public License for more details.
Harald Welte55fe0552010-05-01 16:48:27 +020016 *
Harald Welte0e3e88e2011-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 Welte55fe0552010-05-01 16:48:27 +020019 *
20 */
21
Harald Welte55fe0552010-05-01 16:48:27 +020022#include <sys/socket.h>
23#include <netinet/in.h>
24#include <arpa/inet.h>
Jacob Erlbeckc16c3502014-11-11 14:01:48 +010025#include <time.h>
Harald Welte55fe0552010-05-01 16:48:27 +020026
Pablo Neira Ayusodd5fff42011-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 Welte35ade5e2016-04-20 17:11:43 +020030#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
Harald Welte55fe0552010-05-01 16:48:27 +020031
32#include <openbsc/debug.h>
33#include <openbsc/sgsn.h>
Harald Weltecfb6b282012-06-16 14:59:56 +080034#include <osmocom/gprs/gprs_ns.h>
Harald Weltec1f6bfe2010-05-17 22:58:03 +020035#include <openbsc/gprs_sgsn.h>
Harald Welte58ed1cb2010-05-14 18:59:17 +020036#include <openbsc/vty.h>
Neels Hofmeyrdb1d8012016-12-08 21:22:58 +010037#include <openbsc/gsup_client.h>
Harald Welte55fe0552010-05-01 16:48:27 +020038
Harald Weltebd9591f2010-05-19 19:45:32 +020039#include <osmocom/vty/command.h>
40#include <osmocom/vty/vty.h>
Pablo Neira Ayuso3d31c3a2011-03-28 19:35:00 +020041#include <osmocom/vty/misc.h>
Max0bd04bc2016-06-28 14:10:16 +020042#include <osmocom/crypt/gprs_cipher.h>
Jacob Erlbeck42a1aaf2014-12-19 19:19:46 +010043#include <osmocom/abis/ipa.h>
44
Harald Weltec1f6bfe2010-05-17 22:58:03 +020045#include <pdp.h>
46
Harald Welte55fe0552010-05-01 16:48:27 +020047static struct sgsn_config *g_cfg = NULL;
48
Jacob Erlbeckd7b77732014-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 Erlbeckd04f7cc2014-11-12 10:18:09 +010053 { SGSN_AUTH_POLICY_REMOTE, "remote" },
Jacob Erlbeckd7b77732014-11-04 10:08:37 +010054 { 0, NULL }
55};
56
Harald Welte9b57a3d2015-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
66/* Section 11.2.2 / Table 11.4a MM timers netwokr side */
67#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 Freytherdd69cdf2015-11-02 12:55:07 +010082 doc "\nTimer Value in seconds\n") \
Harald Welte9b57a3d2015-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 Hofmeyr09979ee2015-10-19 14:37:12 +020097DECLARE_TIMER(3322, "Detach request -> accept timer (s)")
Harald Welte9b57a3d2015-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 Freytherdd69cdf2015-11-02 12:55:07 +0100104DECLARE_TIMER(3316, "AA-Ready timer (s)")
Harald Welte9b57a3d2015-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 Erlbeckd7b77732014-11-04 10:08:37 +0100111
Harald Welte493ba622010-07-02 22:47:59 +0200112#define GSM48_MAX_APN_LEN 102 /* 10.5.6.1 */
Neels Hofmeyrf16657a2015-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 Welte493ba622010-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 Freyther41514d92013-07-04 18:44:16 +0200121 unsigned int i = 0;
Harald Welte493ba622010-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 Freythere8e5ef22014-03-23 18:08:26 +0100142char *gprs_pdpaddr2str(uint8_t *pdpa, uint8_t len)
Harald Welte493ba622010-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 Welte55fe0552010-05-01 16:48:27 +0200179static struct cmd_node sgsn_node = {
180 SGSN_NODE,
Harald Welte45362bb2012-08-17 13:16:10 +0200181 "%s(config-sgsn)# ",
Harald Welte55fe0552010-05-01 16:48:27 +0200182 1,
183};
184
185static int config_write_sgsn(struct vty *vty)
186{
Harald Welteeb471c92010-05-18 14:32:29 +0200187 struct sgsn_ggsn_ctx *gctx;
Harald Weltea0879c12013-03-19 11:00:13 +0100188 struct imsi_acl_entry *acl;
Jacob Erlbeck9b3ca642015-02-03 13:47:53 +0100189 struct apn_ctx *actx;
Holger Hans Peter Freyther8adb9c42015-05-25 15:20:27 +0800190 struct ares_addr_node *server;
Harald Welte55fe0552010-05-01 16:48:27 +0200191
192 vty_out(vty, "sgsn%s", VTY_NEWLINE);
193
Harald Weltee0aea392010-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 Weltec1f6bfe2010-05-17 22:58:03 +0200197 llist_for_each_entry(gctx, &sgsn_ggsn_ctxts, list) {
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +0800198 if (gctx->id == UINT32_MAX)
199 continue;
200
Harald Welte31f0a232010-05-19 15:09:09 +0200201 vty_out(vty, " ggsn %u remote-ip %s%s", gctx->id,
Harald Weltec1f6bfe2010-05-17 22:58:03 +0200202 inet_ntoa(gctx->remote_addr), VTY_NEWLINE);
Harald Welte31f0a232010-05-19 15:09:09 +0200203 vty_out(vty, " ggsn %u gtp-version %u%s", gctx->id,
Harald Weltec1f6bfe2010-05-17 22:58:03 +0200204 gctx->gtp_version, VTY_NEWLINE);
Harald Welte55fe0552010-05-01 16:48:27 +0200205 }
206
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +0800207 if (sgsn->cfg.dynamic_lookup)
208 vty_out(vty, " ggsn dynamic%s", VTY_NEWLINE);
209
Holger Hans Peter Freyther8adb9c42015-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
Max0bd04bc2016-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 Erlbeck233715c2014-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);
Max6f9a6ca2016-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 Hofmeyrc21b54d2015-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 Weltea0879c12013-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 Erlbeck9b3ca642015-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 Freyther4b4f7b72015-05-29 15:11:55 +0200245 vty_out(vty, " apn %s imsi-prefix %s ggsn %u%s",
Jacob Erlbeck9b3ca642015-02-03 13:47:53 +0100246 actx->name, actx->imsi_prefix, actx->ggsn->id,
247 VTY_NEWLINE);
248 else
Holger Hans Peter Freyther4b4f7b72015-05-29 15:11:55 +0200249 vty_out(vty, " apn %s ggsn %u%s", actx->name,
Jacob Erlbeck9b3ca642015-02-03 13:47:53 +0100250 actx->ggsn->id, VTY_NEWLINE);
251 }
252
Holger Hans Peter Freyther81283872015-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 Welte9b57a3d2015-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
Philipp91df16c2016-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
Philipp2c6dd812016-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 Welte55fe0552010-05-01 16:48:27 +0200300 return CMD_SUCCESS;
301}
302
Holger Hans Peter Freytherf403c482011-11-05 15:21:16 +0100303#define SGSN_STR "Configure the SGSN\n"
304#define GGSN_STR "Configure the GGSN information\n"
Harald Weltee0aea392010-06-02 12:41:34 +0200305
306DEFUN(cfg_sgsn, cfg_sgsn_cmd,
307 "sgsn",
308 SGSN_STR)
Harald Welte55fe0552010-05-01 16:48:27 +0200309{
310 vty->node = SGSN_NODE;
311 return CMD_SUCCESS;
312}
313
Harald Weltee0aea392010-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 Freytherf403c482011-11-05 15:21:16 +0100317 "Set the IP address for the local GTP bind\n"
318 "IPv4 Address\n")
Harald Weltee0aea392010-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 Weltec1f6bfe2010-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 Freytherf403c482011-11-05 15:21:16 +0100327 GGSN_STR "GGSN Number\n" IP_STR "IPv4 Address\n")
Harald Weltec1f6bfe2010-05-17 22:58:03 +0200328{
329 uint32_t id = atoi(argv[0]);
Harald Welteeb471c92010-05-18 14:32:29 +0200330 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welte55fe0552010-05-01 16:48:27 +0200331
Harald Weltec1f6bfe2010-05-17 22:58:03 +0200332 inet_aton(argv[1], &ggc->remote_addr);
Harald Welte55fe0552010-05-01 16:48:27 +0200333
Harald Weltec1f6bfe2010-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 Welteeb471c92010-05-18 14:32:29 +0200343 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Weltec1f6bfe2010-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 Freytherf403c482011-11-05 15:21:16 +0100351 GGSN_STR "GGSN Number\n" "GTP Version\n"
352 "Version 0\n" "Version 1\n")
Harald Weltec1f6bfe2010-05-17 22:58:03 +0200353{
354 uint32_t id = atoi(argv[0]);
Harald Welteeb471c92010-05-18 14:32:29 +0200355 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Weltec1f6bfe2010-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 Freyther2b1d49a2015-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 Freyther8adb9c42015-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 Erlbeck9b3ca642015-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 Weltec1f6bfe2010-05-17 22:58:03 +0200414DEFUN(cfg_apn_ggsn, cfg_apn_ggsn_cmd,
415 "apn APNAME ggsn <0-255>",
Jacob Erlbeck9b3ca642015-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 Weltec1f6bfe2010-05-17 22:58:03 +0200419{
Jacob Erlbeck9b3ca642015-02-03 13:47:53 +0100420
421 return add_apn_ggsn_mapping(vty, argv[0], "", atoi(argv[1]));
Harald Weltec1f6bfe2010-05-17 22:58:03 +0200422}
Jacob Erlbeck9b3ca642015-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 Weltec1f6bfe2010-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 Welte3ba2ce12010-06-09 15:50:45 +0200440 { GMM_REGISTERED_SUSPENDED, "REGISTERED (SUSPENDED)" },
Harald Weltec1f6bfe2010-05-17 22:58:03 +0200441 { GMM_DEREGISTERED_INIT, "DEREGISTERED (INIT)" },
442 { 0, NULL }
443};
444
Harald Welte734a0c22016-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 Weltec1f6bfe2010-05-17 22:58:03 +0200455static void vty_dump_pdp(struct vty *vty, const char *pfx,
456 struct sgsn_pdp_ctx *pdp)
457{
Jacob Erlbeckd781c7a2014-10-13 10:32:00 +0200458 const char *imsi = pdp->mm ? pdp->mm->imsi : "(detaching)";
Harald Welte734a0c22016-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 Welte493ba622010-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 Welte734a0c22016-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 Welte0fe506b2010-06-10 00:20:12 +0200476 vty_out_rate_ctr_group(vty, " ", pdp->ctrg);
Harald Weltec1f6bfe2010-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 Freyther8b2b5fb2015-05-18 10:00:03 +0200484 vty_out(vty, "%s MSISDN: %s, TLLI: %08x%s HLR: %s",
Harald Weltec28dc2f2015-12-25 19:12:21 +0100485 pfx, mm->msisdn, mm->gb.tlli, mm->hlr, VTY_NEWLINE);
Harald Weltec1f6bfe2010-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,
488 get_value_string(gprs_mm_st_strs, mm->mm_state),
489 mm->ra.mcc, mm->ra.mnc, mm->ra.lac, mm->ra.rac,
Harald Weltec28dc2f2015-12-25 19:12:21 +0100490 mm->gb.cell_id, VTY_NEWLINE);
Harald Weltec1f6bfe2010-05-17 22:58:03 +0200491
Harald Welte8a035af2010-05-18 10:57:45 +0200492 vty_out_rate_ctr_group(vty, " ", mm->ctrg);
493
Harald Weltec1f6bfe2010-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 Erlbeck42a1aaf2014-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 Weltec1f6bfe2010-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 Weltec1f6bfe2010-05-17 22:58:03 +0200569DEFUN(show_pdpctx_all, show_pdpctx_all_cmd,
570 "show pdp-context all",
Holger Hans Peter Freytherf403c482011-11-05 15:21:16 +0100571 SHOW_STR "Display information on PDP Context\n" "Show everything\n")
Harald Weltec1f6bfe2010-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 Welte55fe0552010-05-01 16:48:27 +0200580
Harald Weltea0879c12013-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{
589 const char *op = argv[0];
590 const char *imsi = argv[1];
591 int rc;
592
593 if (!strcmp(op, "add"))
Jacob Erlbeck4760eae2014-10-24 15:11:03 +0200594 rc = sgsn_acl_add(imsi, g_cfg);
Harald Weltea0879c12013-03-19 11:00:13 +0100595 else
Jacob Erlbeck4760eae2014-10-24 15:11:03 +0200596 rc = sgsn_acl_del(imsi, g_cfg);
Harald Weltea0879c12013-03-19 11:00:13 +0100597
598 if (rc < 0) {
Jacob Erlbeckfa7ac452015-01-19 14:29:43 +0100599 vty_out(vty, "%% unable to %s ACL%s", op, VTY_NEWLINE);
600
Harald Weltea0879c12013-03-19 11:00:13 +0100601 return CMD_WARNING;
602 }
603
604 return CMD_SUCCESS;
605}
606
Max0bd04bc2016-06-28 14:10:16 +0200607DEFUN(cfg_encrypt, cfg_encrypt_cmd,
608 "encryption (GEA0|GEA1|GEA2|GEA3|GEA4)",
609 "Set encryption algorithm for SGSN\n"
610 "Use GEA0 (no encryption)\n"
611 "Use GEA1\nUse GEA2\nUse GEA3\nUse GEA4\n")
612{
613 if (!g_cfg->require_authentication) {
614 vty_out(vty, "%% unable to use encryption without "
615 "authentication: adjust auth-policy%s", VTY_NEWLINE);
616 return CMD_WARNING;
617 }
618
619 enum gprs_ciph_algo c = get_string_value(gprs_cipher_names, argv[0]);
620 if (!gprs_cipher_supported(c)) {
621 vty_out(vty, "%% cipher %s is unsupported in current version%s",
622 argv[0], VTY_NEWLINE);
623 return CMD_WARNING;
624 }
625
626 g_cfg->cipher = c;
627
628 return CMD_SUCCESS;
629}
630
Harald Welte2b9693d2013-03-19 11:48:54 +0100631DEFUN(cfg_auth_policy, cfg_auth_policy_cmd,
Jacob Erlbeckd04f7cc2014-11-12 10:18:09 +0100632 "auth-policy (accept-all|closed|acl-only|remote)",
Harald Welte2b9693d2013-03-19 11:48:54 +0100633 "Autorization Policy of SGSN\n"
Jacob Erlbeckd7b77732014-11-04 10:08:37 +0100634 "Accept all IMSIs (DANGEROUS)\n"
635 "Accept only home network subscribers or those in the ACL\n"
Jacob Erlbeckd04f7cc2014-11-12 10:18:09 +0100636 "Accept only subscribers in the ACL\n"
637 "Use remote subscription data only (HLR)\n")
Harald Welte2b9693d2013-03-19 11:48:54 +0100638{
Jacob Erlbeckd7b77732014-11-04 10:08:37 +0100639 int val = get_string_value(sgsn_auth_pol_strs, argv[0]);
Jacob Erlbeckd04f7cc2014-11-12 10:18:09 +0100640 OSMO_ASSERT(val >= SGSN_AUTH_POLICY_OPEN && val <= SGSN_AUTH_POLICY_REMOTE);
Max6f9a6ca2016-07-04 11:09:07 +0200641 if (val == SGSN_AUTH_POLICY_REMOTE) {
642 const char *err = "%% auth-policy remote requires";
643 if (!g_cfg->gsup_server_addr.sin_addr.s_addr) {
644 vty_out(vty, "%s 'gsup remote-ip'%s", err, VTY_NEWLINE);
645 return CMD_WARNING;
646 }
647 if (!g_cfg->gsup_server_port) {
648 vty_out(vty, "%s 'gsup remote-port'%s", err, VTY_NEWLINE);
649 return CMD_WARNING;
650 }
651 }
Jacob Erlbeckd7b77732014-11-04 10:08:37 +0100652 g_cfg->auth_policy = val;
Jacob Erlbeck16b17ed2014-12-17 13:20:08 +0100653 g_cfg->require_authentication = (val == SGSN_AUTH_POLICY_REMOTE);
Jacob Erlbeck6ff7f642014-12-19 18:08:48 +0100654 g_cfg->require_update_location = (val == SGSN_AUTH_POLICY_REMOTE);
Harald Welte2b9693d2013-03-19 11:48:54 +0100655
656 return CMD_SUCCESS;
657}
658
Jacob Erlbeckc16c3502014-11-11 14:01:48 +0100659/* Subscriber */
660#include <openbsc/gsm_subscriber.h>
661
662static void subscr_dump_full_vty(struct vty *vty, struct gsm_subscriber *subscr, int pending)
663{
664 char expire_time[200];
Jacob Erlbeckb1332b62014-12-08 15:52:00 +0100665 struct gsm_auth_tuple *at;
666 int at_idx;
Jacob Erlbeck94a346a2014-12-17 14:03:35 +0100667 struct sgsn_subscriber_pdp_data *pdp;
Jacob Erlbeckc16c3502014-11-11 14:01:48 +0100668
669 vty_out(vty, " ID: %llu, Authorized: %d%s", subscr->id,
670 subscr->authorized, VTY_NEWLINE);
671 if (strlen(subscr->name))
672 vty_out(vty, " Name: '%s'%s", subscr->name, VTY_NEWLINE);
673 if (strlen(subscr->extension))
674 vty_out(vty, " Extension: %s%s", subscr->extension,
675 VTY_NEWLINE);
676 vty_out(vty, " LAC: %d/0x%x%s",
677 subscr->lac, subscr->lac, VTY_NEWLINE);
678 vty_out(vty, " IMSI: %s%s", subscr->imsi, VTY_NEWLINE);
679 if (subscr->tmsi != GSM_RESERVED_TMSI)
680 vty_out(vty, " TMSI: %08X%s", subscr->tmsi,
681 VTY_NEWLINE);
Holger Hans Peter Freyther0f0efd02015-04-23 16:58:33 -0400682 if (subscr->sgsn_data->msisdn_len > 0)
683 vty_out(vty, " MSISDN (BCD): %s%s",
684 osmo_hexdump(subscr->sgsn_data->msisdn,
685 subscr->sgsn_data->msisdn_len),
686 VTY_NEWLINE);
Jacob Erlbeckc16c3502014-11-11 14:01:48 +0100687
688 if (strlen(subscr->equipment.imei) > 0)
689 vty_out(vty, " IMEI: %s%s", subscr->equipment.imei, VTY_NEWLINE);
690
Jacob Erlbeckb1332b62014-12-08 15:52:00 +0100691 for (at_idx = 0; at_idx < ARRAY_SIZE(subscr->sgsn_data->auth_triplets);
692 at_idx++) {
693 at = &subscr->sgsn_data->auth_triplets[at_idx];
694 if (at->key_seq == GSM_KEY_SEQ_INVAL)
695 continue;
696
697 vty_out(vty, " A3A8 tuple (used %d times): ",
698 at->use_count);
699 vty_out(vty, " seq # : %d, ",
700 at->key_seq);
701 vty_out(vty, " RAND : %s, ",
Harald Welte34ef4c52016-04-20 13:13:19 +0200702 osmo_hexdump(at->vec.rand, sizeof(at->vec.rand)));
Jacob Erlbeckb1332b62014-12-08 15:52:00 +0100703 vty_out(vty, " SRES : %s, ",
Harald Welte34ef4c52016-04-20 13:13:19 +0200704 osmo_hexdump(at->vec.sres, sizeof(at->vec.sres)));
Jacob Erlbeckb1332b62014-12-08 15:52:00 +0100705 vty_out(vty, " Kc : %s%s",
Harald Welte34ef4c52016-04-20 13:13:19 +0200706 osmo_hexdump(at->vec.kc, sizeof(at->vec.kc)),
Jacob Erlbeckb1332b62014-12-08 15:52:00 +0100707 VTY_NEWLINE);
708 }
709
Jacob Erlbeck94a346a2014-12-17 14:03:35 +0100710 llist_for_each_entry(pdp, &subscr->sgsn_data->pdp_list, list) {
Holger Hans Peter Freyther703d7c92015-04-23 16:59:04 -0400711 vty_out(vty, " PDP info: Id: %d, Type: 0x%04x, APN: '%s' QoS: %s%s",
Jacob Erlbeck94a346a2014-12-17 14:03:35 +0100712 pdp->context_id, pdp->pdp_type, pdp->apn_str,
Holger Hans Peter Freyther703d7c92015-04-23 16:59:04 -0400713 osmo_hexdump(pdp->qos_subscribed, pdp->qos_subscribed_len),
Jacob Erlbeck94a346a2014-12-17 14:03:35 +0100714 VTY_NEWLINE);
715 }
716
Jacob Erlbeckc16c3502014-11-11 14:01:48 +0100717 /* print the expiration time of a subscriber */
718 if (subscr->expire_lu) {
719 strftime(expire_time, sizeof(expire_time),
720 "%a, %d %b %Y %T %z", localtime(&subscr->expire_lu));
721 expire_time[sizeof(expire_time) - 1] = '\0';
722 vty_out(vty, " Expiration Time: %s%s", expire_time, VTY_NEWLINE);
723 }
724
725 if (subscr->flags)
Jacob Erlbeckb3982c12015-01-06 16:32:41 +0100726 vty_out(vty, " Flags: %s%s%s%s%s%s",
Jacob Erlbeckc16c3502014-11-11 14:01:48 +0100727 subscr->flags & GSM_SUBSCRIBER_FIRST_CONTACT ?
728 "FIRST_CONTACT " : "",
729 subscr->flags & GPRS_SUBSCRIBER_CANCELLED ?
730 "CANCELLED " : "",
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100731 subscr->flags & GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING ?
732 "UPDATE_LOCATION_PENDING " : "",
733 subscr->flags & GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING ?
734 "AUTH_INFO_PENDING " : "",
Jacob Erlbeckb3982c12015-01-06 16:32:41 +0100735 subscr->flags & GPRS_SUBSCRIBER_ENABLE_PURGE ?
736 "ENABLE_PURGE " : "",
Jacob Erlbeckc16c3502014-11-11 14:01:48 +0100737 VTY_NEWLINE);
738
739 vty_out(vty, " Use count: %u%s", subscr->use_count, VTY_NEWLINE);
740}
741
742DEFUN(show_subscr_cache,
743 show_subscr_cache_cmd,
744 "show subscriber cache",
745 SHOW_STR "Show information about subscribers\n"
746 "Display contents of subscriber cache\n")
747{
748 struct gsm_subscriber *subscr;
749
750 llist_for_each_entry(subscr, &active_subscribers, entry) {
751 vty_out(vty, " Subscriber:%s", VTY_NEWLINE);
752 subscr_dump_full_vty(vty, subscr, 0);
753 }
754
755 return CMD_SUCCESS;
756}
757
758#define UPDATE_SUBSCR_STR "update-subscriber imsi IMSI "
759#define UPDATE_SUBSCR_HELP "Update subscriber list\n" \
760 "Use the IMSI to select the subscriber\n" \
761 "The IMSI\n"
762
Jacob Erlbeckb1332b62014-12-08 15:52:00 +0100763#define UPDATE_SUBSCR_INSERT_HELP "Insert data into the subscriber record\n"
764
Jacob Erlbeckb1332b62014-12-08 15:52:00 +0100765DEFUN(update_subscr_insert_auth_triplet, update_subscr_insert_auth_triplet_cmd,
766 UPDATE_SUBSCR_STR "insert auth-triplet <1-5> sres SRES rand RAND kc KC",
767 UPDATE_SUBSCR_HELP
768 UPDATE_SUBSCR_INSERT_HELP
769 "Update authentication triplet\n"
770 "Triplet index\n"
771 "Set SRES value\nSRES value (4 byte) in hex\n"
772 "Set RAND value\nRAND value (16 byte) in hex\n"
773 "Set Kc value\nKc value (8 byte) in hex\n")
774{
775 const char *imsi = argv[0];
776 const int cksn = atoi(argv[1]) - 1;
777 const char *sres_str = argv[2];
778 const char *rand_str = argv[3];
779 const char *kc_str = argv[4];
780 struct gsm_auth_tuple at = {0,};
781
782 struct gsm_subscriber *subscr;
783
Jacob Erlbeck90e3ead2015-01-19 14:11:46 +0100784 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeckb1332b62014-12-08 15:52:00 +0100785 if (!subscr) {
Jacob Erlbeckfa7ac452015-01-19 14:29:43 +0100786 vty_out(vty, "%% unable get subscriber record for %s%s",
787 imsi, VTY_NEWLINE);
Jacob Erlbeckb1332b62014-12-08 15:52:00 +0100788 return CMD_WARNING;
789 }
790
791 OSMO_ASSERT(subscr->sgsn_data);
792
Harald Welte34ef4c52016-04-20 13:13:19 +0200793 if (osmo_hexparse(sres_str, &at.vec.sres[0], sizeof(at.vec.sres)) < 0) {
Jacob Erlbeckfa7ac452015-01-19 14:29:43 +0100794 vty_out(vty, "%% invalid SRES value '%s'%s",
795 sres_str, VTY_NEWLINE);
Jacob Erlbeckb1332b62014-12-08 15:52:00 +0100796 goto failed;
797 }
Harald Welte34ef4c52016-04-20 13:13:19 +0200798 if (osmo_hexparse(rand_str, &at.vec.rand[0], sizeof(at.vec.rand)) < 0) {
Jacob Erlbeckfa7ac452015-01-19 14:29:43 +0100799 vty_out(vty, "%% invalid RAND value '%s'%s",
800 rand_str, VTY_NEWLINE);
Jacob Erlbeckb1332b62014-12-08 15:52:00 +0100801 goto failed;
802 }
Harald Welte34ef4c52016-04-20 13:13:19 +0200803 if (osmo_hexparse(kc_str, &at.vec.kc[0], sizeof(at.vec.kc)) < 0) {
Jacob Erlbeckfa7ac452015-01-19 14:29:43 +0100804 vty_out(vty, "%% invalid Kc value '%s'%s",
805 kc_str, VTY_NEWLINE);
Jacob Erlbeckb1332b62014-12-08 15:52:00 +0100806 goto failed;
807 }
808 at.key_seq = cksn;
809
810 subscr->sgsn_data->auth_triplets[cksn] = at;
811 subscr->sgsn_data->auth_triplets_updated = 1;
812
813 subscr_put(subscr);
814
815 return CMD_SUCCESS;
816
817failed:
818 subscr_put(subscr);
819 return CMD_SUCCESS;
820}
821
Jacob Erlbeckc16c3502014-11-11 14:01:48 +0100822DEFUN(update_subscr_cancel, update_subscr_cancel_cmd,
Jacob Erlbeck3b0d0c02015-01-27 14:56:40 +0100823 UPDATE_SUBSCR_STR "cancel (update-procedure|subscription-withdraw)",
Jacob Erlbeckc16c3502014-11-11 14:01:48 +0100824 UPDATE_SUBSCR_HELP
Jacob Erlbeck3b0d0c02015-01-27 14:56:40 +0100825 "Cancel (remove) subscriber record\n"
826 "The MS moved to another SGSN\n"
827 "The subscription is no longer valid\n")
Jacob Erlbeckc16c3502014-11-11 14:01:48 +0100828{
829 const char *imsi = argv[0];
Jacob Erlbeck3b0d0c02015-01-27 14:56:40 +0100830 const char *cancel_type = argv[1];
Jacob Erlbeckc16c3502014-11-11 14:01:48 +0100831
832 struct gsm_subscriber *subscr;
833
834 subscr = gprs_subscr_get_by_imsi(imsi);
835 if (!subscr) {
Jacob Erlbeckfa7ac452015-01-19 14:29:43 +0100836 vty_out(vty, "%% no subscriber record for %s%s",
837 imsi, VTY_NEWLINE);
Jacob Erlbeckc16c3502014-11-11 14:01:48 +0100838 return CMD_WARNING;
839 }
840
Jacob Erlbeck3b0d0c02015-01-27 14:56:40 +0100841 if (strcmp(cancel_type, "update-procedure") == 0)
842 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
843 else
844 subscr->sgsn_data->error_cause = GMM_CAUSE_IMPL_DETACHED;
845
Jacob Erlbeck7a7d8812015-01-23 13:52:55 +0100846 gprs_subscr_cancel(subscr);
847 subscr_put(subscr);
Jacob Erlbeckc16c3502014-11-11 14:01:48 +0100848
849 return CMD_SUCCESS;
850}
851
Jacob Erlbeck90e3ead2015-01-19 14:11:46 +0100852DEFUN(update_subscr_create, update_subscr_create_cmd,
853 UPDATE_SUBSCR_STR "create",
Jacob Erlbeckc16c3502014-11-11 14:01:48 +0100854 UPDATE_SUBSCR_HELP
Jacob Erlbeck90e3ead2015-01-19 14:11:46 +0100855 "Create a subscriber entry\n")
Jacob Erlbeckc16c3502014-11-11 14:01:48 +0100856{
857 const char *imsi = argv[0];
858
859 struct gsm_subscriber *subscr;
860
861 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeckfa7ac452015-01-19 14:29:43 +0100862 if (subscr) {
863 vty_out(vty, "%% subscriber record already exists for %s%s",
864 imsi, VTY_NEWLINE);
Jacob Erlbeckc16c3502014-11-11 14:01:48 +0100865 return CMD_WARNING;
866 }
867
Jacob Erlbeck90e3ead2015-01-19 14:11:46 +0100868 subscr = gprs_subscr_get_or_create(imsi);
869 subscr->keep_in_ram = 1;
Jacob Erlbeckc16c3502014-11-11 14:01:48 +0100870 subscr_put(subscr);
871
872 return CMD_SUCCESS;
873}
874
Jacob Erlbeckeafb8492015-01-27 12:41:19 +0100875DEFUN(update_subscr_destroy, update_subscr_destroy_cmd,
876 UPDATE_SUBSCR_STR "destroy",
877 UPDATE_SUBSCR_HELP
878 "Destroy a subscriber entry\n")
879{
880 const char *imsi = argv[0];
881
882 struct gsm_subscriber *subscr;
883
884 subscr = gprs_subscr_get_by_imsi(imsi);
885 if (!subscr) {
886 vty_out(vty, "%% subscriber record does not exist for %s%s",
887 imsi, VTY_NEWLINE);
888 return CMD_WARNING;
889 }
890
891 subscr->keep_in_ram = 0;
Jacob Erlbeck3b0d0c02015-01-27 14:56:40 +0100892 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbeckeafb8492015-01-27 12:41:19 +0100893 gprs_subscr_cancel(subscr);
894 if (subscr->use_count > 1)
895 vty_out(vty, "%% subscriber is still in use%s",
896 VTY_NEWLINE);
897 subscr_put(subscr);
898
899 return CMD_SUCCESS;
900}
901
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100902#define UL_ERR_STR "system-failure|data-missing|unexpected-data-value|" \
903 "unknown-subscriber|roaming-not-allowed"
904
905#define UL_ERR_HELP \
906 "Force error code SystemFailure\n" \
907 "Force error code DataMissing\n" \
908 "Force error code UnexpectedDataValue\n" \
909 "Force error code UnknownSubscriber\n" \
910 "Force error code RoamingNotAllowed\n"
911
912DEFUN(update_subscr_update_location_result, update_subscr_update_location_result_cmd,
913 UPDATE_SUBSCR_STR "update-location-result (ok|" UL_ERR_STR ")",
914 UPDATE_SUBSCR_HELP
915 "Complete the update location procedure\n"
916 "The update location request succeeded\n"
917 UL_ERR_HELP)
918{
919 const char *imsi = argv[0];
920 const char *ret_code_str = argv[1];
921
922 struct gsm_subscriber *subscr;
923
Jacob Erlbeckf96779f2015-01-19 11:10:04 +0100924 const struct value_string cause_mapping[] = {
925 { GMM_CAUSE_NET_FAIL, "system-failure" },
926 { GMM_CAUSE_INV_MAND_INFO, "data-missing" },
927 { GMM_CAUSE_PROTO_ERR_UNSPEC, "unexpected-data-value" },
928 { GMM_CAUSE_IMSI_UNKNOWN, "unknown-subscriber" },
929 { GMM_CAUSE_GPRS_NOTALLOWED, "roaming-not-allowed" },
930 { 0, NULL }
931 };
932
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100933 subscr = gprs_subscr_get_by_imsi(imsi);
934 if (!subscr) {
Jacob Erlbeckfa7ac452015-01-19 14:29:43 +0100935 vty_out(vty, "%% unable to get subscriber record for %s%s",
936 imsi, VTY_NEWLINE);
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100937 return CMD_WARNING;
938 }
Jacob Erlbeckf96779f2015-01-19 11:10:04 +0100939
940 if (strcmp(ret_code_str, "ok") == 0) {
941 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100942 subscr->authorized = 1;
Jacob Erlbeckf96779f2015-01-19 11:10:04 +0100943 } else {
944 subscr->sgsn_data->error_cause =
945 get_string_value(cause_mapping, ret_code_str);
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100946 subscr->authorized = 0;
Jacob Erlbeckf96779f2015-01-19 11:10:04 +0100947 }
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100948
949 gprs_subscr_update(subscr);
950
951 subscr_put(subscr);
952
953 return CMD_SUCCESS;
954}
955
956DEFUN(update_subscr_update_auth_info, update_subscr_update_auth_info_cmd,
957 UPDATE_SUBSCR_STR "update-auth-info",
958 UPDATE_SUBSCR_HELP
959 "Complete the send authentication info procedure\n")
960{
961 const char *imsi = argv[0];
962
963 struct gsm_subscriber *subscr;
964
965 subscr = gprs_subscr_get_by_imsi(imsi);
966 if (!subscr) {
Jacob Erlbeckfa7ac452015-01-19 14:29:43 +0100967 vty_out(vty, "%% unable to get subscriber record for %s%s",
968 imsi, VTY_NEWLINE);
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100969 return CMD_WARNING;
970 }
971
972 gprs_subscr_update_auth_info(subscr);
973
974 subscr_put(subscr);
975
976 return CMD_SUCCESS;
977}
978
Jacob Erlbeck233715c2014-12-18 12:46:47 +0100979DEFUN(cfg_gsup_remote_ip, cfg_gsup_remote_ip_cmd,
980 "gsup remote-ip A.B.C.D",
981 "GSUP Parameters\n"
982 "Set the IP address of the remote GSUP server\n"
983 "IPv4 Address\n")
984{
985 inet_aton(argv[0], &g_cfg->gsup_server_addr.sin_addr);
986
987 return CMD_SUCCESS;
988}
989
990DEFUN(cfg_gsup_remote_port, cfg_gsup_remote_port_cmd,
991 "gsup remote-port <0-65535>",
992 "GSUP Parameters\n"
993 "Set the TCP port of the remote GSUP server\n"
994 "Remote TCP port\n")
995{
996 g_cfg->gsup_server_port = atoi(argv[0]);
997
998 return CMD_SUCCESS;
999}
1000
Neels Hofmeyrc21b54d2015-10-12 11:57:38 +02001001DEFUN(cfg_gsup_oap_id, cfg_gsup_oap_id_cmd,
1002 "gsup oap-id <0-65535>",
1003 "GSUP Parameters\n"
1004 "Set the SGSN's OAP client ID\nOAP client ID (0 == disabled)\n")
1005{
1006 /* VTY ensures range */
1007 g_cfg->oap.client_id = (uint16_t)atoi(argv[0]);
1008 return CMD_SUCCESS;
1009}
1010
1011DEFUN(cfg_gsup_oap_k, cfg_gsup_oap_k_cmd,
1012 "gsup oap-k K",
1013 "GSUP Parameters\n"
1014 "Set the OAP shared secret K\nK value (16 byte) hex\n")
1015{
1016 const char *k = argv[0];
1017
1018 g_cfg->oap.secret_k_present = 0;
1019
1020 if ((!k) || (strlen(k) == 0))
1021 goto disable;
1022
1023 int k_len = osmo_hexparse(k,
1024 g_cfg->oap.secret_k,
1025 sizeof(g_cfg->oap.secret_k));
1026 if (k_len != 16) {
1027 vty_out(vty, "%% need exactly 16 octets for oap-k, got %d.%s",
1028 k_len, VTY_NEWLINE);
1029 goto disable;
1030 }
1031
1032 g_cfg->oap.secret_k_present = 1;
1033 return CMD_SUCCESS;
1034
1035disable:
1036 if (g_cfg->oap.client_id > 0) {
1037 vty_out(vty, "%% OAP client ID set, but invalid oap-k value disables OAP.%s",
1038 VTY_NEWLINE);
1039 return CMD_WARNING;
1040 }
1041 return CMD_SUCCESS;
1042}
1043
1044DEFUN(cfg_gsup_oap_opc, cfg_gsup_oap_opc_cmd,
1045 "gsup oap-opc OPC",
1046 "GSUP Parameters\n"
1047 "Set the OAP shared secret OPC\nOPC value (16 byte) hex\n")
1048{
1049 const char *opc = argv[0];
1050
1051 g_cfg->oap.secret_opc_present = 0;
1052
1053 if ((!opc) || (strlen(opc) == 0))
1054 goto disable;
1055
1056 int opc_len = osmo_hexparse(opc,
1057 g_cfg->oap.secret_opc,
1058 sizeof(g_cfg->oap.secret_opc));
1059 if (opc_len != 16) {
1060 vty_out(vty, "%% need exactly 16 octets for oap-opc, got %d.%s",
1061 opc_len, VTY_NEWLINE);
1062 goto disable;
1063 }
1064
1065 g_cfg->oap.secret_opc_present = 1;
1066 return CMD_SUCCESS;
1067
1068disable:
1069 if (g_cfg->oap.client_id > 0) {
1070 vty_out(vty, "%% OAP client ID set, but invalid oap-opc value disables OAP.%s",
1071 VTY_NEWLINE);
1072 return CMD_WARNING;
1073 }
1074 return CMD_SUCCESS;
1075}
1076
Holger Hans Peter Freyther37391482015-02-06 16:23:29 +01001077DEFUN(cfg_apn_name, cfg_apn_name_cmd,
1078 "access-point-name NAME",
1079 "Configure a global list of allowed APNs\n"
1080 "Add this NAME to the list\n")
1081{
1082 return add_apn_ggsn_mapping(vty, argv[0], "", 0);
1083}
1084
1085DEFUN(cfg_no_apn_name, cfg_no_apn_name_cmd,
1086 "no access-point-name NAME",
1087 NO_STR "Configure a global list of allowed APNs\n"
1088 "Remove entry with NAME\n")
1089{
1090 struct apn_ctx *apn_ctx = sgsn_apn_ctx_by_name(argv[0], "");
1091 if (!apn_ctx)
1092 return CMD_SUCCESS;
1093
1094 sgsn_apn_ctx_free(apn_ctx);
1095 return CMD_SUCCESS;
1096}
1097
Holger Hans Peter Freyther81283872015-05-06 17:46:08 +02001098DEFUN(cfg_cdr_filename, cfg_cdr_filename_cmd,
1099 "cdr filename NAME",
1100 "CDR\nSet filename\nname\n")
1101{
1102 talloc_free(g_cfg->cdr.filename);
1103 g_cfg->cdr.filename = talloc_strdup(tall_vty_ctx, argv[0]);
1104 return CMD_SUCCESS;
1105}
1106
1107DEFUN(cfg_no_cdr_filename, cfg_no_cdr_filename_cmd,
1108 "no cdr filename",
1109 NO_STR "CDR\nDisable CDR generation\n")
1110{
1111 talloc_free(g_cfg->cdr.filename);
1112 g_cfg->cdr.filename = NULL;
1113 return CMD_SUCCESS;
1114}
1115
1116DEFUN(cfg_cdr_interval, cfg_cdr_interval_cmd,
1117 "cdr interval <1-2147483647>",
1118 "CDR\nPDP periodic log interval\nSeconds\n")
1119{
1120 g_cfg->cdr.interval = atoi(argv[0]);
1121 return CMD_SUCCESS;
1122}
1123
Philipp91df16c2016-08-26 17:00:21 +02001124#define COMPRESSION_STR "Configure compression\n"
1125DEFUN(cfg_no_comp_rfc1144, cfg_no_comp_rfc1144_cmd,
1126 "no compression rfc1144",
1127 NO_STR COMPRESSION_STR "disable rfc1144 TCP/IP header compression\n")
1128{
1129 g_cfg->pcomp_rfc1144.active = 0;
1130 g_cfg->pcomp_rfc1144.passive = 0;
1131 return CMD_SUCCESS;
1132}
1133
1134DEFUN(cfg_comp_rfc1144, cfg_comp_rfc1144_cmd,
1135 "compression rfc1144 active slots <1-256>",
1136 COMPRESSION_STR
1137 "RFC1144 Header compresion scheme\n"
1138 "Compression is actively proposed\n"
1139 "Number of compression state slots\n"
1140 "Number of compression state slots\n")
1141{
1142 g_cfg->pcomp_rfc1144.active = 1;
1143 g_cfg->pcomp_rfc1144.passive = 1;
1144 g_cfg->pcomp_rfc1144.s01 = atoi(argv[0]) - 1;
1145 return CMD_SUCCESS;
1146}
1147
1148DEFUN(cfg_comp_rfc1144p, cfg_comp_rfc1144p_cmd,
1149 "compression rfc1144 passive",
1150 COMPRESSION_STR
1151 "RFC1144 Header compresion scheme\n"
1152 "Compression is available on request\n")
1153{
1154 g_cfg->pcomp_rfc1144.active = 0;
1155 g_cfg->pcomp_rfc1144.passive = 1;
1156 return CMD_SUCCESS;
1157}
1158
Philipp2c6dd812016-09-02 13:38:01 +02001159DEFUN(cfg_no_comp_v42bis, cfg_no_comp_v42bis_cmd,
1160 "no compression v42bis",
1161 NO_STR COMPRESSION_STR "disable V.42bis data compression\n")
1162{
1163 g_cfg->dcomp_v42bis.active = 0;
1164 g_cfg->dcomp_v42bis.passive = 0;
1165 return CMD_SUCCESS;
1166}
1167
1168DEFUN(cfg_comp_v42bis, cfg_comp_v42bis_cmd,
1169 "compression v42bis active direction (ms|sgsn|both) codewords <512-65535> strlen <6-250>",
1170 COMPRESSION_STR
1171 "V.42bis data compresion scheme\n"
1172 "Compression is actively proposed\n"
1173 "Direction in which the compression shall be active (p0)\n"
1174 "Compress ms->sgsn direction only\n"
1175 "Compress sgsn->ms direction only\n"
1176 "Both directions\n"
1177 "Number of codewords (p1)\n"
1178 "Number of codewords\n"
1179 "Maximum string length (p2)\n" "Maximum string length\n")
1180{
1181 g_cfg->dcomp_v42bis.active = 1;
1182 g_cfg->dcomp_v42bis.passive = 1;
1183
1184 switch (argv[0][0]) {
1185 case 'm':
1186 g_cfg->dcomp_v42bis.p0 = 1;
1187 break;
1188 case 's':
1189 g_cfg->dcomp_v42bis.p0 = 2;
1190 break;
1191 case 'b':
1192 g_cfg->dcomp_v42bis.p0 = 3;
1193 break;
1194 }
1195
1196 g_cfg->dcomp_v42bis.p1 = atoi(argv[1]);
1197 g_cfg->dcomp_v42bis.p2 = atoi(argv[2]);
1198 return CMD_SUCCESS;
1199}
1200
1201DEFUN(cfg_comp_v42bisp, cfg_comp_v42bisp_cmd,
1202 "compression v42bis passive",
1203 COMPRESSION_STR
1204 "V.42bis data compresion scheme\n"
1205 "Compression is available on request\n")
1206{
1207 g_cfg->dcomp_v42bis.active = 0;
1208 g_cfg->dcomp_v42bis.passive = 1;
1209 return CMD_SUCCESS;
1210}
1211
Harald Welte55fe0552010-05-01 16:48:27 +02001212int sgsn_vty_init(void)
1213{
Harald Weltec1f6bfe2010-05-17 22:58:03 +02001214 install_element_ve(&show_sgsn_cmd);
1215 //install_element_ve(&show_mmctx_tlli_cmd);
1216 install_element_ve(&show_mmctx_imsi_cmd);
1217 install_element_ve(&show_mmctx_all_cmd);
1218 install_element_ve(&show_pdpctx_all_cmd);
Jacob Erlbeckc16c3502014-11-11 14:01:48 +01001219 install_element_ve(&show_subscr_cache_cmd);
1220
Jacob Erlbeckb1332b62014-12-08 15:52:00 +01001221 install_element(ENABLE_NODE, &update_subscr_insert_auth_triplet_cmd);
Jacob Erlbeck90e3ead2015-01-19 14:11:46 +01001222 install_element(ENABLE_NODE, &update_subscr_create_cmd);
Jacob Erlbeckeafb8492015-01-27 12:41:19 +01001223 install_element(ENABLE_NODE, &update_subscr_destroy_cmd);
Jacob Erlbeckc16c3502014-11-11 14:01:48 +01001224 install_element(ENABLE_NODE, &update_subscr_cancel_cmd);
Jacob Erlbeck828059f2014-11-28 14:55:25 +01001225 install_element(ENABLE_NODE, &update_subscr_update_location_result_cmd);
1226 install_element(ENABLE_NODE, &update_subscr_update_auth_info_cmd);
Harald Welte55fe0552010-05-01 16:48:27 +02001227
1228 install_element(CONFIG_NODE, &cfg_sgsn_cmd);
1229 install_node(&sgsn_node, config_write_sgsn);
Jacob Erlbeckf414e852013-10-29 09:30:30 +01001230 vty_install_default(SGSN_NODE);
Harald Weltee0aea392010-06-02 12:41:34 +02001231 install_element(SGSN_NODE, &cfg_sgsn_bind_addr_cmd);
Harald Weltec1f6bfe2010-05-17 22:58:03 +02001232 install_element(SGSN_NODE, &cfg_ggsn_remote_ip_cmd);
1233 //install_element(SGSN_NODE, &cfg_ggsn_remote_port_cmd);
1234 install_element(SGSN_NODE, &cfg_ggsn_gtp_version_cmd);
Harald Weltea0879c12013-03-19 11:00:13 +01001235 install_element(SGSN_NODE, &cfg_imsi_acl_cmd);
Harald Welte2b9693d2013-03-19 11:48:54 +01001236 install_element(SGSN_NODE, &cfg_auth_policy_cmd);
Max0bd04bc2016-06-28 14:10:16 +02001237 install_element(SGSN_NODE, &cfg_encrypt_cmd);
Jacob Erlbeck233715c2014-12-18 12:46:47 +01001238 install_element(SGSN_NODE, &cfg_gsup_remote_ip_cmd);
1239 install_element(SGSN_NODE, &cfg_gsup_remote_port_cmd);
Neels Hofmeyrc21b54d2015-10-12 11:57:38 +02001240 install_element(SGSN_NODE, &cfg_gsup_oap_id_cmd);
1241 install_element(SGSN_NODE, &cfg_gsup_oap_k_cmd);
1242 install_element(SGSN_NODE, &cfg_gsup_oap_opc_cmd);
Jacob Erlbeck9b3ca642015-02-03 13:47:53 +01001243 install_element(SGSN_NODE, &cfg_apn_ggsn_cmd);
1244 install_element(SGSN_NODE, &cfg_apn_imsi_ggsn_cmd);
Holger Hans Peter Freyther37391482015-02-06 16:23:29 +01001245 install_element(SGSN_NODE, &cfg_apn_name_cmd);
1246 install_element(SGSN_NODE, &cfg_no_apn_name_cmd);
Holger Hans Peter Freyther81283872015-05-06 17:46:08 +02001247 install_element(SGSN_NODE, &cfg_cdr_filename_cmd);
1248 install_element(SGSN_NODE, &cfg_no_cdr_filename_cmd);
1249 install_element(SGSN_NODE, &cfg_cdr_interval_cmd);
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001250 install_element(SGSN_NODE, &cfg_ggsn_dynamic_lookup_cmd);
Holger Hans Peter Freyther8adb9c42015-05-25 15:20:27 +08001251 install_element(SGSN_NODE, &cfg_grx_ggsn_cmd);
Harald Welte55fe0552010-05-01 16:48:27 +02001252
Harald Welte9b57a3d2015-08-15 19:08:21 +02001253 install_element(SGSN_NODE, &cfg_sgsn_T3312_cmd);
1254 install_element(SGSN_NODE, &cfg_sgsn_T3322_cmd);
1255 install_element(SGSN_NODE, &cfg_sgsn_T3350_cmd);
1256 install_element(SGSN_NODE, &cfg_sgsn_T3360_cmd);
1257 install_element(SGSN_NODE, &cfg_sgsn_T3370_cmd);
1258 install_element(SGSN_NODE, &cfg_sgsn_T3313_cmd);
1259 install_element(SGSN_NODE, &cfg_sgsn_T3314_cmd);
1260 install_element(SGSN_NODE, &cfg_sgsn_T3316_cmd);
1261 install_element(SGSN_NODE, &cfg_sgsn_T3385_cmd);
1262 install_element(SGSN_NODE, &cfg_sgsn_T3386_cmd);
1263 install_element(SGSN_NODE, &cfg_sgsn_T3395_cmd);
1264 install_element(SGSN_NODE, &cfg_sgsn_T3397_cmd);
1265
Philipp91df16c2016-08-26 17:00:21 +02001266 install_element(SGSN_NODE, &cfg_no_comp_rfc1144_cmd);
1267 install_element(SGSN_NODE, &cfg_comp_rfc1144_cmd);
1268 install_element(SGSN_NODE, &cfg_comp_rfc1144p_cmd);
Philipp2c6dd812016-09-02 13:38:01 +02001269 install_element(SGSN_NODE, &cfg_no_comp_v42bis_cmd);
1270 install_element(SGSN_NODE, &cfg_comp_v42bis_cmd);
1271 install_element(SGSN_NODE, &cfg_comp_v42bisp_cmd);
Harald Welte55fe0552010-05-01 16:48:27 +02001272 return 0;
1273}
1274
1275int sgsn_parse_config(const char *config_file, struct sgsn_config *cfg)
1276{
1277 int rc;
1278
1279 g_cfg = cfg;
Harald Weltea0879c12013-03-19 11:00:13 +01001280
Harald Welte9b57a3d2015-08-15 19:08:21 +02001281 g_cfg->timers.T3312 = GSM0408_T3312_SECS;
1282 g_cfg->timers.T3322 = GSM0408_T3322_SECS;
1283 g_cfg->timers.T3350 = GSM0408_T3350_SECS;
1284 g_cfg->timers.T3360 = GSM0408_T3360_SECS;
1285 g_cfg->timers.T3370 = GSM0408_T3370_SECS;
1286 g_cfg->timers.T3313 = GSM0408_T3313_SECS;
1287 g_cfg->timers.T3314 = GSM0408_T3314_SECS;
1288 g_cfg->timers.T3316 = GSM0408_T3316_SECS;
1289 g_cfg->timers.T3385 = GSM0408_T3385_SECS;
1290 g_cfg->timers.T3386 = GSM0408_T3386_SECS;
1291 g_cfg->timers.T3395 = GSM0408_T3395_SECS;
1292 g_cfg->timers.T3397 = GSM0408_T3397_SECS;
1293
Harald Welte40152872010-05-16 20:52:23 +02001294 rc = vty_read_config_file(config_file, NULL);
Harald Welte55fe0552010-05-01 16:48:27 +02001295 if (rc < 0) {
1296 fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
1297 return rc;
1298 }
1299
1300 return 0;
1301}