blob: 21c865b3d4ad15856feb020d005ec537fadf23ac [file] [log] [blame]
Harald Welte288be162010-05-01 16:48:27 +02001/*
Harald Welte7f6da482013-03-19 11:00:13 +01002 * (C) 2010-2013 by Harald Welte <laforge@gnumonks.org>
Harald Welte288be162010-05-01 16:48:27 +02003 * (C) 2010 by On-Waves
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02004 * (C) 2015 by Holger Hans Peter Freyther
Harald Welte288be162010-05-01 16:48:27 +02005 * All Rights Reserved
6 *
7 * This program is free software; you can redistribute it and/or modify
Harald Welte9af6ddf2011-01-01 15:25:50 +01008 * it under the terms of the GNU Affero General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
Harald Welte288be162010-05-01 16:48:27 +020010 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Harald Welte9af6ddf2011-01-01 15:25:50 +010015 * GNU Affero General Public License for more details.
Harald Welte288be162010-05-01 16:48:27 +020016 *
Harald Welte9af6ddf2011-01-01 15:25:50 +010017 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
Harald Welte288be162010-05-01 16:48:27 +020019 *
20 */
21
Harald Welte288be162010-05-01 16:48:27 +020022#include <sys/socket.h>
23#include <netinet/in.h>
24#include <arpa/inet.h>
Jacob Erlbeck207f4a52014-11-11 14:01:48 +010025#include <time.h>
Harald Welte288be162010-05-01 16:48:27 +020026
Pablo Neira Ayuso136f4532011-03-22 16:47:59 +010027#include <osmocom/core/talloc.h>
28#include <osmocom/core/utils.h>
29#include <osmocom/core/rate_ctr.h>
Harald Welte53373bc2016-04-20 17:11:43 +020030#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
Harald Welte288be162010-05-01 16:48:27 +020031
32#include <openbsc/debug.h>
33#include <openbsc/sgsn.h>
Harald Welteea34a4e2012-06-16 14:59:56 +080034#include <osmocom/gprs/gprs_ns.h>
Harald Welted193cb32010-05-17 22:58:03 +020035#include <openbsc/gprs_sgsn.h>
Harald Welte62ab20c2010-05-14 18:59:17 +020036#include <openbsc/vty.h>
Neels Hofmeyreaaee922016-12-08 21:22:58 +010037#include <openbsc/gsup_client.h>
Harald Welte288be162010-05-01 16:48:27 +020038
Harald Welte4b037e42010-05-19 19:45:32 +020039#include <osmocom/vty/command.h>
40#include <osmocom/vty/vty.h>
Pablo Neira Ayuso6110a3f2011-03-28 19:35:00 +020041#include <osmocom/vty/misc.h>
Max93408ae2016-06-28 14:10:16 +020042#include <osmocom/crypt/gprs_cipher.h>
Jacob Erlbeck80547992014-12-19 19:19:46 +010043#include <osmocom/abis/ipa.h>
44
Harald Welted193cb32010-05-17 22:58:03 +020045#include <pdp.h>
46
Harald Welte288be162010-05-01 16:48:27 +020047static struct sgsn_config *g_cfg = NULL;
48
Jacob Erlbeck106f5472014-11-04 10:08:37 +010049const struct value_string sgsn_auth_pol_strs[] = {
50 { SGSN_AUTH_POLICY_OPEN, "accept-all" },
51 { SGSN_AUTH_POLICY_CLOSED, "closed" },
52 { SGSN_AUTH_POLICY_ACL_ONLY, "acl-only" },
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +010053 { SGSN_AUTH_POLICY_REMOTE, "remote" },
Jacob Erlbeck106f5472014-11-04 10:08:37 +010054 { 0, NULL }
55};
56
Harald Welte94508822015-08-15 19:08:21 +020057/* Section 11.2.2 / Table 11.3a GPRS Mobility management timers – MS side */
58#define GSM0408_T3312_SECS (10*60) /* periodic RAU interval, default 54min */
59
60/* Section 11.2.2 / Table 11.4 MM timers netwokr side */
61#define GSM0408_T3322_SECS 6 /* DETACH_REQ -> DETACH_ACC */
62#define GSM0408_T3350_SECS 6 /* waiting for ATT/RAU/TMSI COMPL */
63#define GSM0408_T3360_SECS 6 /* waiting for AUTH/CIPH RESP */
64#define GSM0408_T3370_SECS 6 /* waiting for ID RESP */
65
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 Freytherfe60cfb2015-11-02 12:55:07 +010082 doc "\nTimer Value in seconds\n") \
Harald Welte94508822015-08-15 19:08:21 +020083{ \
84 int value = atoi(argv[0]); \
85 \
86 if (value < 0 || value > 65535) { \
87 vty_out(vty, "Timer value %s out of range.%s", \
88 argv[0], VTY_NEWLINE); \
89 return CMD_WARNING; \
90 } \
91 \
92 g_cfg->timers.T##number = value; \
93 return CMD_SUCCESS; \
94}
95
96DECLARE_TIMER(3312, "Periodic RA Update timer (s)")
Neels Hofmeyr65482c92015-10-19 14:37:12 +020097DECLARE_TIMER(3322, "Detach request -> accept timer (s)")
Harald Welte94508822015-08-15 19:08:21 +020098DECLARE_TIMER(3350, "Waiting for ATT/RAU/TMSI_COMPL timer (s)")
99DECLARE_TIMER(3360, "Waiting for AUTH/CIPH response timer (s)")
100DECLARE_TIMER(3370, "Waiting for IDENTITY response timer (s)")
101
102DECLARE_TIMER(3313, "Waiting for paging response timer (s)")
103DECLARE_TIMER(3314, "Force to STANDBY on expiry timer (s)")
Holger Hans Peter Freytherfe60cfb2015-11-02 12:55:07 +0100104DECLARE_TIMER(3316, "AA-Ready timer (s)")
Harald Welte94508822015-08-15 19:08:21 +0200105
106DECLARE_TIMER(3385, "Wait for ACT PDP CTX REQ timer (s)")
107DECLARE_TIMER(3386, "Wait for MODIFY PDP CTX ACK timer (s)")
108DECLARE_TIMER(3395, "Wait for DEACT PDP CTX ACK timer (s)")
109DECLARE_TIMER(3397, "Wait for DEACT AA PDP CTX ACK timer (s)")
110
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100111
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200112#define GSM48_MAX_APN_LEN 102 /* 10.5.6.1 */
Neels Hofmeyr30f7bcb2015-11-08 20:34:47 +0100113/* TODO: consolidate with gprs_apn_to_str(). */
114/** Copy apn to a static buffer, replacing the length octets in apn_enc with '.'
115 * and terminating with a '\0'. Return the static buffer.
116 * len: the length of the encoded APN (which has no terminating zero).
117 */
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200118static char *gprs_apn2str(uint8_t *apn, unsigned int len)
119{
120 static char apnbuf[GSM48_MAX_APN_LEN+1];
Holger Hans Peter Freyther80e03652013-07-04 18:44:16 +0200121 unsigned int i = 0;
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200122
123 if (!apn)
124 return "";
125
126 if (len > sizeof(apnbuf)-1)
127 len = sizeof(apnbuf)-1;
128
129 memcpy(apnbuf, apn, len);
130 apnbuf[len] = '\0';
131
132 /* replace the domain name step sizes with dots */
133 while (i < len) {
134 unsigned int step = apnbuf[i];
135 apnbuf[i] = '.';
136 i += step+1;
137 }
138
139 return apnbuf+1;
140}
141
Holger Hans Peter Freythera2730302014-03-23 18:08:26 +0100142char *gprs_pdpaddr2str(uint8_t *pdpa, uint8_t len)
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200143{
144 static char str[INET6_ADDRSTRLEN + 10];
145
146 if (!pdpa || len < 2)
147 return "none";
148
149 switch (pdpa[0] & 0x0f) {
150 case PDP_TYPE_ORG_IETF:
151 switch (pdpa[1]) {
152 case PDP_TYPE_N_IETF_IPv4:
153 if (len < 2 + 4)
154 break;
155 strcpy(str, "IPv4 ");
156 inet_ntop(AF_INET, pdpa+2, str+5, sizeof(str)-5);
157 return str;
158 case PDP_TYPE_N_IETF_IPv6:
159 if (len < 2 + 8)
160 break;
161 strcpy(str, "IPv6 ");
162 inet_ntop(AF_INET6, pdpa+2, str+5, sizeof(str)-5);
163 return str;
164 default:
165 break;
166 }
167 break;
168 case PDP_TYPE_ORG_ETSI:
169 if (pdpa[1] == PDP_TYPE_N_ETSI_PPP)
170 return "PPP";
171 break;
172 default:
173 break;
174 }
175
176 return "invalid";
177}
178
Harald Welte288be162010-05-01 16:48:27 +0200179static struct cmd_node sgsn_node = {
180 SGSN_NODE,
Harald Welte570ce242012-08-17 13:16:10 +0200181 "%s(config-sgsn)# ",
Harald Welte288be162010-05-01 16:48:27 +0200182 1,
183};
184
185static int config_write_sgsn(struct vty *vty)
186{
Harald Welte77289c22010-05-18 14:32:29 +0200187 struct sgsn_ggsn_ctx *gctx;
Harald Welte7f6da482013-03-19 11:00:13 +0100188 struct imsi_acl_entry *acl;
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100189 struct apn_ctx *actx;
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800190 struct ares_addr_node *server;
Harald Welte288be162010-05-01 16:48:27 +0200191
192 vty_out(vty, "sgsn%s", VTY_NEWLINE);
193
Harald Weltee300d002010-06-02 12:41:34 +0200194 vty_out(vty, " gtp local-ip %s%s",
195 inet_ntoa(g_cfg->gtp_listenaddr.sin_addr), VTY_NEWLINE);
196
Harald Welted193cb32010-05-17 22:58:03 +0200197 llist_for_each_entry(gctx, &sgsn_ggsn_ctxts, list) {
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800198 if (gctx->id == UINT32_MAX)
199 continue;
200
Harald Welteff3bde82010-05-19 15:09:09 +0200201 vty_out(vty, " ggsn %u remote-ip %s%s", gctx->id,
Harald Welted193cb32010-05-17 22:58:03 +0200202 inet_ntoa(gctx->remote_addr), VTY_NEWLINE);
Harald Welteff3bde82010-05-19 15:09:09 +0200203 vty_out(vty, " ggsn %u gtp-version %u%s", gctx->id,
Harald Welted193cb32010-05-17 22:58:03 +0200204 gctx->gtp_version, VTY_NEWLINE);
Harald Welte288be162010-05-01 16:48:27 +0200205 }
206
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800207 if (sgsn->cfg.dynamic_lookup)
208 vty_out(vty, " ggsn dynamic%s", VTY_NEWLINE);
209
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800210 for (server = sgsn->ares_servers; server; server = server->next)
211 vty_out(vty, " grx-dns-add %s%s", inet_ntoa(server->addr.addr4), VTY_NEWLINE);
212
Max93408ae2016-06-28 14:10:16 +0200213 if (g_cfg->cipher != GPRS_ALGO_GEA0)
214 vty_out(vty, " encryption %s%s",
215 get_value_string(gprs_cipher_names, g_cfg->cipher),
216 VTY_NEWLINE);
Jacob Erlbeck39f040d2014-12-18 12:46:47 +0100217 if (g_cfg->gsup_server_addr.sin_addr.s_addr)
218 vty_out(vty, " gsup remote-ip %s%s",
219 inet_ntoa(g_cfg->gsup_server_addr.sin_addr), VTY_NEWLINE);
220 if (g_cfg->gsup_server_port)
221 vty_out(vty, " gsup remote-port %d%s",
222 g_cfg->gsup_server_port, VTY_NEWLINE);
Max176b62a2016-07-04 11:09:07 +0200223 vty_out(vty, " auth-policy %s%s",
224 get_value_string(sgsn_auth_pol_strs, g_cfg->auth_policy),
225 VTY_NEWLINE);
Neels Hofmeyr568a7272015-10-12 11:57:38 +0200226
227 vty_out(vty, " gsup oap-id %d%s",
228 (int)g_cfg->oap.client_id, VTY_NEWLINE);
229 if (g_cfg->oap.secret_k_present != 0)
230 vty_out(vty, " gsup oap-k %s%s",
231 osmo_hexdump_nospc(g_cfg->oap.secret_k, sizeof(g_cfg->oap.secret_k)),
232 VTY_NEWLINE);
233 if (g_cfg->oap.secret_opc_present != 0)
234 vty_out(vty, " gsup oap-opc %s%s",
235 osmo_hexdump_nospc(g_cfg->oap.secret_opc, sizeof(g_cfg->oap.secret_opc)),
236 VTY_NEWLINE);
237
Harald Welte7f6da482013-03-19 11:00:13 +0100238 llist_for_each_entry(acl, &g_cfg->imsi_acl, list)
239 vty_out(vty, " imsi-acl add %s%s", acl->imsi, VTY_NEWLINE);
240
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100241 if (llist_empty(&sgsn_apn_ctxts))
242 vty_out(vty, " ! apn * ggsn 0%s", VTY_NEWLINE);
243 llist_for_each_entry(actx, &sgsn_apn_ctxts, list) {
244 if (strlen(actx->imsi_prefix) > 0)
Holger Hans Peter Freytherb7ae0b32015-05-29 15:11:55 +0200245 vty_out(vty, " apn %s imsi-prefix %s ggsn %u%s",
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100246 actx->name, actx->imsi_prefix, actx->ggsn->id,
247 VTY_NEWLINE);
248 else
Holger Hans Peter Freytherb7ae0b32015-05-29 15:11:55 +0200249 vty_out(vty, " apn %s ggsn %u%s", actx->name,
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100250 actx->ggsn->id, VTY_NEWLINE);
251 }
252
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +0200253 if (g_cfg->cdr.filename)
254 vty_out(vty, " cdr filename %s%s", g_cfg->cdr.filename, VTY_NEWLINE);
255 else
256 vty_out(vty, " no cdr filename%s", VTY_NEWLINE);
257 vty_out(vty, " cdr interval %d%s", g_cfg->cdr.interval, VTY_NEWLINE);
258
Harald Welte94508822015-08-15 19:08:21 +0200259 vty_out(vty, " timer t3312 %d%s", g_cfg->timers.T3312, VTY_NEWLINE);
260 vty_out(vty, " timer t3322 %d%s", g_cfg->timers.T3322, VTY_NEWLINE);
261 vty_out(vty, " timer t3350 %d%s", g_cfg->timers.T3350, VTY_NEWLINE);
262 vty_out(vty, " timer t3360 %d%s", g_cfg->timers.T3360, VTY_NEWLINE);
263 vty_out(vty, " timer t3370 %d%s", g_cfg->timers.T3370, VTY_NEWLINE);
264 vty_out(vty, " timer t3313 %d%s", g_cfg->timers.T3313, VTY_NEWLINE);
265 vty_out(vty, " timer t3314 %d%s", g_cfg->timers.T3314, VTY_NEWLINE);
266 vty_out(vty, " timer t3316 %d%s", g_cfg->timers.T3316, VTY_NEWLINE);
267 vty_out(vty, " timer t3385 %d%s", g_cfg->timers.T3385, VTY_NEWLINE);
268 vty_out(vty, " timer t3386 %d%s", g_cfg->timers.T3386, VTY_NEWLINE);
269 vty_out(vty, " timer t3395 %d%s", g_cfg->timers.T3395, VTY_NEWLINE);
270 vty_out(vty, " timer t3397 %d%s", g_cfg->timers.T3397, VTY_NEWLINE);
271
Philippf1f34362016-08-26 17:00:21 +0200272 if (g_cfg->pcomp_rfc1144.active) {
273 vty_out(vty, " compression rfc1144 active slots %d%s",
274 g_cfg->pcomp_rfc1144.s01 + 1, VTY_NEWLINE);
275 } else if (g_cfg->pcomp_rfc1144.passive) {
276 vty_out(vty, " compression rfc1144 passive%s", VTY_NEWLINE);
277 } else
278 vty_out(vty, " no compression rfc1144%s", VTY_NEWLINE);
279
Philipp73f83d52016-09-02 13:38:01 +0200280 if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 1) {
281 vty_out(vty,
282 " compression v42bis active direction sgsn codewords %d strlen %d%s",
283 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
284 VTY_NEWLINE);
285 } else if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 2) {
286 vty_out(vty,
287 " compression v42bis active direction ms codewords %d strlen %d%s",
288 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
289 VTY_NEWLINE);
290 } else if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 3) {
291 vty_out(vty,
292 " compression v42bis active direction both codewords %d strlen %d%s",
293 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
294 VTY_NEWLINE);
295 } else if (g_cfg->dcomp_v42bis.passive) {
296 vty_out(vty, " compression v42bis passive%s", VTY_NEWLINE);
297 } else
298 vty_out(vty, " no compression v42bis%s", VTY_NEWLINE);
299
Harald Welte288be162010-05-01 16:48:27 +0200300 return CMD_SUCCESS;
301}
302
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100303#define SGSN_STR "Configure the SGSN\n"
304#define GGSN_STR "Configure the GGSN information\n"
Harald Weltee300d002010-06-02 12:41:34 +0200305
306DEFUN(cfg_sgsn, cfg_sgsn_cmd,
307 "sgsn",
308 SGSN_STR)
Harald Welte288be162010-05-01 16:48:27 +0200309{
310 vty->node = SGSN_NODE;
311 return CMD_SUCCESS;
312}
313
Harald Weltee300d002010-06-02 12:41:34 +0200314DEFUN(cfg_sgsn_bind_addr, cfg_sgsn_bind_addr_cmd,
315 "gtp local-ip A.B.C.D",
316 "GTP Parameters\n"
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100317 "Set the IP address for the local GTP bind\n"
318 "IPv4 Address\n")
Harald Weltee300d002010-06-02 12:41:34 +0200319{
320 inet_aton(argv[0], &g_cfg->gtp_listenaddr.sin_addr);
321
322 return CMD_SUCCESS;
323}
324
Harald Welted193cb32010-05-17 22:58:03 +0200325DEFUN(cfg_ggsn_remote_ip, cfg_ggsn_remote_ip_cmd,
326 "ggsn <0-255> remote-ip A.B.C.D",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100327 GGSN_STR "GGSN Number\n" IP_STR "IPv4 Address\n")
Harald Welted193cb32010-05-17 22:58:03 +0200328{
329 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200330 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welte288be162010-05-01 16:48:27 +0200331
Harald Welted193cb32010-05-17 22:58:03 +0200332 inet_aton(argv[1], &ggc->remote_addr);
Harald Welte288be162010-05-01 16:48:27 +0200333
Harald Welted193cb32010-05-17 22:58:03 +0200334 return CMD_SUCCESS;
335}
336
337#if 0
338DEFUN(cfg_ggsn_remote_port, cfg_ggsn_remote_port_cmd,
339 "ggsn <0-255> remote-port <0-65535>",
340 "")
341{
342 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200343 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welted193cb32010-05-17 22:58:03 +0200344 uint16_t port = atoi(argv[1]);
345
346}
347#endif
348
349DEFUN(cfg_ggsn_gtp_version, cfg_ggsn_gtp_version_cmd,
350 "ggsn <0-255> gtp-version (0|1)",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100351 GGSN_STR "GGSN Number\n" "GTP Version\n"
352 "Version 0\n" "Version 1\n")
Harald Welted193cb32010-05-17 22:58:03 +0200353{
354 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200355 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welted193cb32010-05-17 22:58:03 +0200356
357 if (atoi(argv[1]))
358 ggc->gtp_version = 1;
359 else
360 ggc->gtp_version = 0;
361
362 return CMD_SUCCESS;
363}
364
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800365DEFUN(cfg_ggsn_dynamic_lookup, cfg_ggsn_dynamic_lookup_cmd,
366 "ggsn dynamic",
367 GGSN_STR "Enable dynamic GRX based look-up (requires restart)\n")
368{
369 sgsn->cfg.dynamic_lookup = 1;
370 return CMD_SUCCESS;
371}
372
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800373DEFUN(cfg_grx_ggsn, cfg_grx_ggsn_cmd,
374 "grx-dns-add A.B.C.D",
375 "Add DNS server\nIPv4 address\n")
376{
377 struct ares_addr_node *node = talloc_zero(tall_bsc_ctx, struct ares_addr_node);
378 node->family = AF_INET;
379 inet_aton(argv[0], &node->addr.addr4);
380
381 node->next = sgsn->ares_servers;
382 sgsn->ares_servers = node;
383 return CMD_SUCCESS;
384}
385
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100386#define APN_STR "Configure the information per APN\n"
387#define APN_GW_STR "The APN gateway name optionally prefixed by '*' (wildcard)\n"
388
389static int add_apn_ggsn_mapping(struct vty *vty, const char *apn_str,
390 const char *imsi_prefix, int ggsn_id)
391{
392 struct apn_ctx *actx;
393 struct sgsn_ggsn_ctx *ggsn;
394
395 ggsn = sgsn_ggsn_ctx_by_id(ggsn_id);
396 if (ggsn == NULL) {
397 vty_out(vty, "%% a GGSN with id %d has not been defined%s",
398 ggsn_id, VTY_NEWLINE);
399 return CMD_WARNING;
400 }
401
402 actx = sgsn_apn_ctx_find_alloc(apn_str, imsi_prefix);
403 if (!actx) {
404 vty_out(vty, "%% unable to create APN context for %s/%s%s",
405 apn_str, imsi_prefix, VTY_NEWLINE);
406 return CMD_WARNING;
407 }
408
409 actx->ggsn = ggsn;
410
411 return CMD_SUCCESS;
412}
413
Harald Welted193cb32010-05-17 22:58:03 +0200414DEFUN(cfg_apn_ggsn, cfg_apn_ggsn_cmd,
415 "apn APNAME ggsn <0-255>",
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100416 APN_STR APN_GW_STR
417 "Select the GGSN to use when the APN gateway prefix matches\n"
418 "The GGSN id")
Harald Welted193cb32010-05-17 22:58:03 +0200419{
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100420
421 return add_apn_ggsn_mapping(vty, argv[0], "", atoi(argv[1]));
Harald Welted193cb32010-05-17 22:58:03 +0200422}
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100423
424DEFUN(cfg_apn_imsi_ggsn, cfg_apn_imsi_ggsn_cmd,
425 "apn APNAME imsi-prefix IMSIPRE ggsn <0-255>",
426 APN_STR APN_GW_STR
427 "Restrict rule to a certain IMSI prefix\n"
428 "An IMSI prefix\n"
429 "Select the GGSN to use when APN gateway and IMSI prefix match\n"
430 "The GGSN id")
431{
432
433 return add_apn_ggsn_mapping(vty, argv[0], argv[1], atoi(argv[2]));
434}
Harald Welted193cb32010-05-17 22:58:03 +0200435
436const struct value_string gprs_mm_st_strs[] = {
437 { GMM_DEREGISTERED, "DEREGISTERED" },
438 { GMM_COMMON_PROC_INIT, "COMMON PROCEDURE (INIT)" },
439 { GMM_REGISTERED_NORMAL, "REGISTERED (NORMAL)" },
Harald Weltebffeff82010-06-09 15:50:45 +0200440 { GMM_REGISTERED_SUSPENDED, "REGISTERED (SUSPENDED)" },
Harald Welted193cb32010-05-17 22:58:03 +0200441 { GMM_DEREGISTERED_INIT, "DEREGISTERED (INIT)" },
442 { 0, NULL }
443};
444
445static void vty_dump_pdp(struct vty *vty, const char *pfx,
446 struct sgsn_pdp_ctx *pdp)
447{
Jacob Erlbeck99985b52014-10-13 10:32:00 +0200448 const char *imsi = pdp->mm ? pdp->mm->imsi : "(detaching)";
Harald Welted193cb32010-05-17 22:58:03 +0200449 vty_out(vty, "%sPDP Context IMSI: %s, SAPI: %u, NSAPI: %u%s",
Jacob Erlbeck99985b52014-10-13 10:32:00 +0200450 pfx, imsi, pdp->sapi, pdp->nsapi, VTY_NEWLINE);
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200451 vty_out(vty, "%s APN: %s%s", pfx,
452 gprs_apn2str(pdp->lib->apn_use.v, pdp->lib->apn_use.l),
453 VTY_NEWLINE);
454 vty_out(vty, "%s PDP Address: %s%s", pfx,
455 gprs_pdpaddr2str(pdp->lib->eua.v, pdp->lib->eua.l),
456 VTY_NEWLINE);
Harald Welteefbdee92010-06-10 00:20:12 +0200457 vty_out_rate_ctr_group(vty, " ", pdp->ctrg);
Harald Welted193cb32010-05-17 22:58:03 +0200458}
459
460static void vty_dump_mmctx(struct vty *vty, const char *pfx,
461 struct sgsn_mm_ctx *mm, int pdp)
462{
463 vty_out(vty, "%sMM Context for IMSI %s, IMEI %s, P-TMSI %08x%s",
464 pfx, mm->imsi, mm->imei, mm->p_tmsi, VTY_NEWLINE);
Holger Hans Peter Freyther8ee13e22015-05-18 10:00:03 +0200465 vty_out(vty, "%s MSISDN: %s, TLLI: %08x%s HLR: %s",
Harald Weltef97ee042015-12-25 19:12:21 +0100466 pfx, mm->msisdn, mm->gb.tlli, mm->hlr, VTY_NEWLINE);
Harald Welted193cb32010-05-17 22:58:03 +0200467 vty_out(vty, "%s MM State: %s, Routeing Area: %u-%u-%u-%u, "
468 "Cell ID: %u%s", pfx,
469 get_value_string(gprs_mm_st_strs, mm->mm_state),
470 mm->ra.mcc, mm->ra.mnc, mm->ra.lac, mm->ra.rac,
Harald Weltef97ee042015-12-25 19:12:21 +0100471 mm->gb.cell_id, VTY_NEWLINE);
Harald Welted193cb32010-05-17 22:58:03 +0200472
Harald Welte8acd88f2010-05-18 10:57:45 +0200473 vty_out_rate_ctr_group(vty, " ", mm->ctrg);
474
Harald Welted193cb32010-05-17 22:58:03 +0200475 if (pdp) {
476 struct sgsn_pdp_ctx *pdp;
477
478 llist_for_each_entry(pdp, &mm->pdp_list, list)
479 vty_dump_pdp(vty, " ", pdp);
480 }
481}
482
483DEFUN(show_sgsn, show_sgsn_cmd, "show sgsn",
484 SHOW_STR "Display information about the SGSN")
485{
Jacob Erlbeck80547992014-12-19 19:19:46 +0100486 if (sgsn->gsup_client) {
487 struct ipa_client_conn *link = sgsn->gsup_client->link;
488 vty_out(vty,
489 " Remote authorization: %sconnected to %s:%d via GSUP%s",
490 sgsn->gsup_client->is_connected ? "" : "not ",
491 link->addr, link->port,
492 VTY_NEWLINE);
493 }
Harald Welted193cb32010-05-17 22:58:03 +0200494 /* FIXME: statistics */
495 return CMD_SUCCESS;
496}
497
498#define MMCTX_STR "MM Context\n"
499#define INCLUDE_PDP_STR "Include PDP Context Information\n"
500
501#if 0
502DEFUN(show_mmctx_tlli, show_mmctx_tlli_cmd,
503 "show mm-context tlli HEX [pdp]",
504 SHOW_STR MMCTX_STR "Identify by TLLI\n" "TLLI\n" INCLUDE_PDP_STR)
505{
506 uint32_t tlli;
507 struct sgsn_mm_ctx *mm;
508
509 tlli = strtoul(argv[0], NULL, 16);
510 mm = sgsn_mm_ctx_by_tlli(tlli);
511 if (!mm) {
512 vty_out(vty, "No MM context for TLLI %08x%s",
513 tlli, VTY_NEWLINE);
514 return CMD_WARNING;
515 }
516 vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
517 return CMD_SUCCESS;
518}
519#endif
520
521DEFUN(swow_mmctx_imsi, show_mmctx_imsi_cmd,
522 "show mm-context imsi IMSI [pdp]",
523 SHOW_STR MMCTX_STR "Identify by IMSI\n" "IMSI of the MM Context\n"
524 INCLUDE_PDP_STR)
525{
526 struct sgsn_mm_ctx *mm;
527
528 mm = sgsn_mm_ctx_by_imsi(argv[0]);
529 if (!mm) {
530 vty_out(vty, "No MM context for IMSI %s%s",
531 argv[0], VTY_NEWLINE);
532 return CMD_WARNING;
533 }
534 vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
535 return CMD_SUCCESS;
536}
537
538DEFUN(swow_mmctx_all, show_mmctx_all_cmd,
539 "show mm-context all [pdp]",
540 SHOW_STR MMCTX_STR "All MM Contexts\n" INCLUDE_PDP_STR)
541{
542 struct sgsn_mm_ctx *mm;
543
544 llist_for_each_entry(mm, &sgsn_mm_ctxts, list)
545 vty_dump_mmctx(vty, "", mm, argv[0] ? 1 : 0);
546
547 return CMD_SUCCESS;
548}
549
Harald Welted193cb32010-05-17 22:58:03 +0200550DEFUN(show_pdpctx_all, show_pdpctx_all_cmd,
551 "show pdp-context all",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100552 SHOW_STR "Display information on PDP Context\n" "Show everything\n")
Harald Welted193cb32010-05-17 22:58:03 +0200553{
554 struct sgsn_pdp_ctx *pdp;
555
556 llist_for_each_entry(pdp, &sgsn_pdp_ctxts, g_list)
557 vty_dump_pdp(vty, "", pdp);
558
559 return CMD_SUCCESS;
560}
Harald Welte288be162010-05-01 16:48:27 +0200561
Harald Welte7f6da482013-03-19 11:00:13 +0100562
563DEFUN(imsi_acl, cfg_imsi_acl_cmd,
564 "imsi-acl (add|del) IMSI",
565 "Access Control List of foreign IMSIs\n"
566 "Add IMSI to ACL\n"
567 "Remove IMSI from ACL\n"
568 "IMSI of subscriber\n")
569{
570 const char *op = argv[0];
571 const char *imsi = argv[1];
572 int rc;
573
574 if (!strcmp(op, "add"))
Jacob Erlbeck3b5d4072014-10-24 15:11:03 +0200575 rc = sgsn_acl_add(imsi, g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +0100576 else
Jacob Erlbeck3b5d4072014-10-24 15:11:03 +0200577 rc = sgsn_acl_del(imsi, g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +0100578
579 if (rc < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100580 vty_out(vty, "%% unable to %s ACL%s", op, VTY_NEWLINE);
581
Harald Welte7f6da482013-03-19 11:00:13 +0100582 return CMD_WARNING;
583 }
584
585 return CMD_SUCCESS;
586}
587
Max93408ae2016-06-28 14:10:16 +0200588DEFUN(cfg_encrypt, cfg_encrypt_cmd,
589 "encryption (GEA0|GEA1|GEA2|GEA3|GEA4)",
590 "Set encryption algorithm for SGSN\n"
591 "Use GEA0 (no encryption)\n"
592 "Use GEA1\nUse GEA2\nUse GEA3\nUse GEA4\n")
593{
594 if (!g_cfg->require_authentication) {
595 vty_out(vty, "%% unable to use encryption without "
596 "authentication: adjust auth-policy%s", VTY_NEWLINE);
597 return CMD_WARNING;
598 }
599
600 enum gprs_ciph_algo c = get_string_value(gprs_cipher_names, argv[0]);
601 if (!gprs_cipher_supported(c)) {
602 vty_out(vty, "%% cipher %s is unsupported in current version%s",
603 argv[0], VTY_NEWLINE);
604 return CMD_WARNING;
605 }
606
607 g_cfg->cipher = c;
608
609 return CMD_SUCCESS;
610}
611
Harald Welte3dfb5492013-03-19 11:48:54 +0100612DEFUN(cfg_auth_policy, cfg_auth_policy_cmd,
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100613 "auth-policy (accept-all|closed|acl-only|remote)",
Harald Welte3dfb5492013-03-19 11:48:54 +0100614 "Autorization Policy of SGSN\n"
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100615 "Accept all IMSIs (DANGEROUS)\n"
616 "Accept only home network subscribers or those in the ACL\n"
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100617 "Accept only subscribers in the ACL\n"
618 "Use remote subscription data only (HLR)\n")
Harald Welte3dfb5492013-03-19 11:48:54 +0100619{
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100620 int val = get_string_value(sgsn_auth_pol_strs, argv[0]);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100621 OSMO_ASSERT(val >= SGSN_AUTH_POLICY_OPEN && val <= SGSN_AUTH_POLICY_REMOTE);
Max176b62a2016-07-04 11:09:07 +0200622 if (val == SGSN_AUTH_POLICY_REMOTE) {
623 const char *err = "%% auth-policy remote requires";
624 if (!g_cfg->gsup_server_addr.sin_addr.s_addr) {
625 vty_out(vty, "%s 'gsup remote-ip'%s", err, VTY_NEWLINE);
626 return CMD_WARNING;
627 }
628 if (!g_cfg->gsup_server_port) {
629 vty_out(vty, "%s 'gsup remote-port'%s", err, VTY_NEWLINE);
630 return CMD_WARNING;
631 }
632 }
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100633 g_cfg->auth_policy = val;
Jacob Erlbeck9d4f46c2014-12-17 13:20:08 +0100634 g_cfg->require_authentication = (val == SGSN_AUTH_POLICY_REMOTE);
Jacob Erlbeck771573c2014-12-19 18:08:48 +0100635 g_cfg->require_update_location = (val == SGSN_AUTH_POLICY_REMOTE);
Harald Welte3dfb5492013-03-19 11:48:54 +0100636
637 return CMD_SUCCESS;
638}
639
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100640/* Subscriber */
641#include <openbsc/gsm_subscriber.h>
642
643static void subscr_dump_full_vty(struct vty *vty, struct gsm_subscriber *subscr, int pending)
644{
645 char expire_time[200];
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100646 struct gsm_auth_tuple *at;
647 int at_idx;
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100648 struct sgsn_subscriber_pdp_data *pdp;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100649
650 vty_out(vty, " ID: %llu, Authorized: %d%s", subscr->id,
651 subscr->authorized, VTY_NEWLINE);
652 if (strlen(subscr->name))
653 vty_out(vty, " Name: '%s'%s", subscr->name, VTY_NEWLINE);
654 if (strlen(subscr->extension))
655 vty_out(vty, " Extension: %s%s", subscr->extension,
656 VTY_NEWLINE);
657 vty_out(vty, " LAC: %d/0x%x%s",
658 subscr->lac, subscr->lac, VTY_NEWLINE);
659 vty_out(vty, " IMSI: %s%s", subscr->imsi, VTY_NEWLINE);
660 if (subscr->tmsi != GSM_RESERVED_TMSI)
661 vty_out(vty, " TMSI: %08X%s", subscr->tmsi,
662 VTY_NEWLINE);
Holger Hans Peter Freytherf7b38262015-04-23 16:58:33 -0400663 if (subscr->sgsn_data->msisdn_len > 0)
664 vty_out(vty, " MSISDN (BCD): %s%s",
665 osmo_hexdump(subscr->sgsn_data->msisdn,
666 subscr->sgsn_data->msisdn_len),
667 VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100668
669 if (strlen(subscr->equipment.imei) > 0)
670 vty_out(vty, " IMEI: %s%s", subscr->equipment.imei, VTY_NEWLINE);
671
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100672 for (at_idx = 0; at_idx < ARRAY_SIZE(subscr->sgsn_data->auth_triplets);
673 at_idx++) {
674 at = &subscr->sgsn_data->auth_triplets[at_idx];
675 if (at->key_seq == GSM_KEY_SEQ_INVAL)
676 continue;
677
678 vty_out(vty, " A3A8 tuple (used %d times): ",
679 at->use_count);
680 vty_out(vty, " seq # : %d, ",
681 at->key_seq);
682 vty_out(vty, " RAND : %s, ",
Harald Welte121e9a42016-04-20 13:13:19 +0200683 osmo_hexdump(at->vec.rand, sizeof(at->vec.rand)));
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100684 vty_out(vty, " SRES : %s, ",
Harald Welte121e9a42016-04-20 13:13:19 +0200685 osmo_hexdump(at->vec.sres, sizeof(at->vec.sres)));
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100686 vty_out(vty, " Kc : %s%s",
Harald Welte121e9a42016-04-20 13:13:19 +0200687 osmo_hexdump(at->vec.kc, sizeof(at->vec.kc)),
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100688 VTY_NEWLINE);
689 }
690
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100691 llist_for_each_entry(pdp, &subscr->sgsn_data->pdp_list, list) {
Holger Hans Peter Freytherd05e0692015-04-23 16:59:04 -0400692 vty_out(vty, " PDP info: Id: %d, Type: 0x%04x, APN: '%s' QoS: %s%s",
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100693 pdp->context_id, pdp->pdp_type, pdp->apn_str,
Holger Hans Peter Freytherd05e0692015-04-23 16:59:04 -0400694 osmo_hexdump(pdp->qos_subscribed, pdp->qos_subscribed_len),
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100695 VTY_NEWLINE);
696 }
697
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100698 /* print the expiration time of a subscriber */
699 if (subscr->expire_lu) {
700 strftime(expire_time, sizeof(expire_time),
701 "%a, %d %b %Y %T %z", localtime(&subscr->expire_lu));
702 expire_time[sizeof(expire_time) - 1] = '\0';
703 vty_out(vty, " Expiration Time: %s%s", expire_time, VTY_NEWLINE);
704 }
705
706 if (subscr->flags)
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100707 vty_out(vty, " Flags: %s%s%s%s%s%s",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100708 subscr->flags & GSM_SUBSCRIBER_FIRST_CONTACT ?
709 "FIRST_CONTACT " : "",
710 subscr->flags & GPRS_SUBSCRIBER_CANCELLED ?
711 "CANCELLED " : "",
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100712 subscr->flags & GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING ?
713 "UPDATE_LOCATION_PENDING " : "",
714 subscr->flags & GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING ?
715 "AUTH_INFO_PENDING " : "",
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100716 subscr->flags & GPRS_SUBSCRIBER_ENABLE_PURGE ?
717 "ENABLE_PURGE " : "",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100718 VTY_NEWLINE);
719
720 vty_out(vty, " Use count: %u%s", subscr->use_count, VTY_NEWLINE);
721}
722
723DEFUN(show_subscr_cache,
724 show_subscr_cache_cmd,
725 "show subscriber cache",
726 SHOW_STR "Show information about subscribers\n"
727 "Display contents of subscriber cache\n")
728{
729 struct gsm_subscriber *subscr;
730
731 llist_for_each_entry(subscr, &active_subscribers, entry) {
732 vty_out(vty, " Subscriber:%s", VTY_NEWLINE);
733 subscr_dump_full_vty(vty, subscr, 0);
734 }
735
736 return CMD_SUCCESS;
737}
738
739#define UPDATE_SUBSCR_STR "update-subscriber imsi IMSI "
740#define UPDATE_SUBSCR_HELP "Update subscriber list\n" \
741 "Use the IMSI to select the subscriber\n" \
742 "The IMSI\n"
743
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100744#define UPDATE_SUBSCR_INSERT_HELP "Insert data into the subscriber record\n"
745
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100746DEFUN(update_subscr_insert_auth_triplet, update_subscr_insert_auth_triplet_cmd,
747 UPDATE_SUBSCR_STR "insert auth-triplet <1-5> sres SRES rand RAND kc KC",
748 UPDATE_SUBSCR_HELP
749 UPDATE_SUBSCR_INSERT_HELP
750 "Update authentication triplet\n"
751 "Triplet index\n"
752 "Set SRES value\nSRES value (4 byte) in hex\n"
753 "Set RAND value\nRAND value (16 byte) in hex\n"
754 "Set Kc value\nKc value (8 byte) in hex\n")
755{
756 const char *imsi = argv[0];
757 const int cksn = atoi(argv[1]) - 1;
758 const char *sres_str = argv[2];
759 const char *rand_str = argv[3];
760 const char *kc_str = argv[4];
761 struct gsm_auth_tuple at = {0,};
762
763 struct gsm_subscriber *subscr;
764
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100765 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100766 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100767 vty_out(vty, "%% unable get subscriber record for %s%s",
768 imsi, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100769 return CMD_WARNING;
770 }
771
772 OSMO_ASSERT(subscr->sgsn_data);
773
Harald Welte121e9a42016-04-20 13:13:19 +0200774 if (osmo_hexparse(sres_str, &at.vec.sres[0], sizeof(at.vec.sres)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100775 vty_out(vty, "%% invalid SRES value '%s'%s",
776 sres_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100777 goto failed;
778 }
Harald Welte121e9a42016-04-20 13:13:19 +0200779 if (osmo_hexparse(rand_str, &at.vec.rand[0], sizeof(at.vec.rand)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100780 vty_out(vty, "%% invalid RAND value '%s'%s",
781 rand_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100782 goto failed;
783 }
Harald Welte121e9a42016-04-20 13:13:19 +0200784 if (osmo_hexparse(kc_str, &at.vec.kc[0], sizeof(at.vec.kc)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100785 vty_out(vty, "%% invalid Kc value '%s'%s",
786 kc_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100787 goto failed;
788 }
789 at.key_seq = cksn;
790
791 subscr->sgsn_data->auth_triplets[cksn] = at;
792 subscr->sgsn_data->auth_triplets_updated = 1;
793
794 subscr_put(subscr);
795
796 return CMD_SUCCESS;
797
798failed:
799 subscr_put(subscr);
800 return CMD_SUCCESS;
801}
802
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100803DEFUN(update_subscr_cancel, update_subscr_cancel_cmd,
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100804 UPDATE_SUBSCR_STR "cancel (update-procedure|subscription-withdraw)",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100805 UPDATE_SUBSCR_HELP
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100806 "Cancel (remove) subscriber record\n"
807 "The MS moved to another SGSN\n"
808 "The subscription is no longer valid\n")
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100809{
810 const char *imsi = argv[0];
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100811 const char *cancel_type = argv[1];
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100812
813 struct gsm_subscriber *subscr;
814
815 subscr = gprs_subscr_get_by_imsi(imsi);
816 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100817 vty_out(vty, "%% no subscriber record for %s%s",
818 imsi, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100819 return CMD_WARNING;
820 }
821
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100822 if (strcmp(cancel_type, "update-procedure") == 0)
823 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
824 else
825 subscr->sgsn_data->error_cause = GMM_CAUSE_IMPL_DETACHED;
826
Jacob Erlbeck37139e52015-01-23 13:52:55 +0100827 gprs_subscr_cancel(subscr);
828 subscr_put(subscr);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100829
830 return CMD_SUCCESS;
831}
832
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100833DEFUN(update_subscr_create, update_subscr_create_cmd,
834 UPDATE_SUBSCR_STR "create",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100835 UPDATE_SUBSCR_HELP
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100836 "Create a subscriber entry\n")
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100837{
838 const char *imsi = argv[0];
839
840 struct gsm_subscriber *subscr;
841
842 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100843 if (subscr) {
844 vty_out(vty, "%% subscriber record already exists for %s%s",
845 imsi, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100846 return CMD_WARNING;
847 }
848
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100849 subscr = gprs_subscr_get_or_create(imsi);
850 subscr->keep_in_ram = 1;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100851 subscr_put(subscr);
852
853 return CMD_SUCCESS;
854}
855
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100856DEFUN(update_subscr_destroy, update_subscr_destroy_cmd,
857 UPDATE_SUBSCR_STR "destroy",
858 UPDATE_SUBSCR_HELP
859 "Destroy a subscriber entry\n")
860{
861 const char *imsi = argv[0];
862
863 struct gsm_subscriber *subscr;
864
865 subscr = gprs_subscr_get_by_imsi(imsi);
866 if (!subscr) {
867 vty_out(vty, "%% subscriber record does not exist for %s%s",
868 imsi, VTY_NEWLINE);
869 return CMD_WARNING;
870 }
871
872 subscr->keep_in_ram = 0;
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100873 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100874 gprs_subscr_cancel(subscr);
875 if (subscr->use_count > 1)
876 vty_out(vty, "%% subscriber is still in use%s",
877 VTY_NEWLINE);
878 subscr_put(subscr);
879
880 return CMD_SUCCESS;
881}
882
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100883#define UL_ERR_STR "system-failure|data-missing|unexpected-data-value|" \
884 "unknown-subscriber|roaming-not-allowed"
885
886#define UL_ERR_HELP \
887 "Force error code SystemFailure\n" \
888 "Force error code DataMissing\n" \
889 "Force error code UnexpectedDataValue\n" \
890 "Force error code UnknownSubscriber\n" \
891 "Force error code RoamingNotAllowed\n"
892
893DEFUN(update_subscr_update_location_result, update_subscr_update_location_result_cmd,
894 UPDATE_SUBSCR_STR "update-location-result (ok|" UL_ERR_STR ")",
895 UPDATE_SUBSCR_HELP
896 "Complete the update location procedure\n"
897 "The update location request succeeded\n"
898 UL_ERR_HELP)
899{
900 const char *imsi = argv[0];
901 const char *ret_code_str = argv[1];
902
903 struct gsm_subscriber *subscr;
904
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100905 const struct value_string cause_mapping[] = {
906 { GMM_CAUSE_NET_FAIL, "system-failure" },
907 { GMM_CAUSE_INV_MAND_INFO, "data-missing" },
908 { GMM_CAUSE_PROTO_ERR_UNSPEC, "unexpected-data-value" },
909 { GMM_CAUSE_IMSI_UNKNOWN, "unknown-subscriber" },
910 { GMM_CAUSE_GPRS_NOTALLOWED, "roaming-not-allowed" },
911 { 0, NULL }
912 };
913
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100914 subscr = gprs_subscr_get_by_imsi(imsi);
915 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100916 vty_out(vty, "%% unable to get subscriber record for %s%s",
917 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100918 return CMD_WARNING;
919 }
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100920
921 if (strcmp(ret_code_str, "ok") == 0) {
922 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100923 subscr->authorized = 1;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100924 } else {
925 subscr->sgsn_data->error_cause =
926 get_string_value(cause_mapping, ret_code_str);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100927 subscr->authorized = 0;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100928 }
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100929
930 gprs_subscr_update(subscr);
931
932 subscr_put(subscr);
933
934 return CMD_SUCCESS;
935}
936
937DEFUN(update_subscr_update_auth_info, update_subscr_update_auth_info_cmd,
938 UPDATE_SUBSCR_STR "update-auth-info",
939 UPDATE_SUBSCR_HELP
940 "Complete the send authentication info procedure\n")
941{
942 const char *imsi = argv[0];
943
944 struct gsm_subscriber *subscr;
945
946 subscr = gprs_subscr_get_by_imsi(imsi);
947 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100948 vty_out(vty, "%% unable to get subscriber record for %s%s",
949 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100950 return CMD_WARNING;
951 }
952
953 gprs_subscr_update_auth_info(subscr);
954
955 subscr_put(subscr);
956
957 return CMD_SUCCESS;
958}
959
Jacob Erlbeck39f040d2014-12-18 12:46:47 +0100960DEFUN(cfg_gsup_remote_ip, cfg_gsup_remote_ip_cmd,
961 "gsup remote-ip A.B.C.D",
962 "GSUP Parameters\n"
963 "Set the IP address of the remote GSUP server\n"
964 "IPv4 Address\n")
965{
966 inet_aton(argv[0], &g_cfg->gsup_server_addr.sin_addr);
967
968 return CMD_SUCCESS;
969}
970
971DEFUN(cfg_gsup_remote_port, cfg_gsup_remote_port_cmd,
972 "gsup remote-port <0-65535>",
973 "GSUP Parameters\n"
974 "Set the TCP port of the remote GSUP server\n"
975 "Remote TCP port\n")
976{
977 g_cfg->gsup_server_port = atoi(argv[0]);
978
979 return CMD_SUCCESS;
980}
981
Neels Hofmeyr568a7272015-10-12 11:57:38 +0200982DEFUN(cfg_gsup_oap_id, cfg_gsup_oap_id_cmd,
983 "gsup oap-id <0-65535>",
984 "GSUP Parameters\n"
985 "Set the SGSN's OAP client ID\nOAP client ID (0 == disabled)\n")
986{
987 /* VTY ensures range */
988 g_cfg->oap.client_id = (uint16_t)atoi(argv[0]);
989 return CMD_SUCCESS;
990}
991
992DEFUN(cfg_gsup_oap_k, cfg_gsup_oap_k_cmd,
993 "gsup oap-k K",
994 "GSUP Parameters\n"
995 "Set the OAP shared secret K\nK value (16 byte) hex\n")
996{
997 const char *k = argv[0];
998
999 g_cfg->oap.secret_k_present = 0;
1000
1001 if ((!k) || (strlen(k) == 0))
1002 goto disable;
1003
1004 int k_len = osmo_hexparse(k,
1005 g_cfg->oap.secret_k,
1006 sizeof(g_cfg->oap.secret_k));
1007 if (k_len != 16) {
1008 vty_out(vty, "%% need exactly 16 octets for oap-k, got %d.%s",
1009 k_len, VTY_NEWLINE);
1010 goto disable;
1011 }
1012
1013 g_cfg->oap.secret_k_present = 1;
1014 return CMD_SUCCESS;
1015
1016disable:
1017 if (g_cfg->oap.client_id > 0) {
1018 vty_out(vty, "%% OAP client ID set, but invalid oap-k value disables OAP.%s",
1019 VTY_NEWLINE);
1020 return CMD_WARNING;
1021 }
1022 return CMD_SUCCESS;
1023}
1024
1025DEFUN(cfg_gsup_oap_opc, cfg_gsup_oap_opc_cmd,
1026 "gsup oap-opc OPC",
1027 "GSUP Parameters\n"
1028 "Set the OAP shared secret OPC\nOPC value (16 byte) hex\n")
1029{
1030 const char *opc = argv[0];
1031
1032 g_cfg->oap.secret_opc_present = 0;
1033
1034 if ((!opc) || (strlen(opc) == 0))
1035 goto disable;
1036
1037 int opc_len = osmo_hexparse(opc,
1038 g_cfg->oap.secret_opc,
1039 sizeof(g_cfg->oap.secret_opc));
1040 if (opc_len != 16) {
1041 vty_out(vty, "%% need exactly 16 octets for oap-opc, got %d.%s",
1042 opc_len, VTY_NEWLINE);
1043 goto disable;
1044 }
1045
1046 g_cfg->oap.secret_opc_present = 1;
1047 return CMD_SUCCESS;
1048
1049disable:
1050 if (g_cfg->oap.client_id > 0) {
1051 vty_out(vty, "%% OAP client ID set, but invalid oap-opc value disables OAP.%s",
1052 VTY_NEWLINE);
1053 return CMD_WARNING;
1054 }
1055 return CMD_SUCCESS;
1056}
1057
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001058DEFUN(cfg_apn_name, cfg_apn_name_cmd,
1059 "access-point-name NAME",
1060 "Configure a global list of allowed APNs\n"
1061 "Add this NAME to the list\n")
1062{
1063 return add_apn_ggsn_mapping(vty, argv[0], "", 0);
1064}
1065
1066DEFUN(cfg_no_apn_name, cfg_no_apn_name_cmd,
1067 "no access-point-name NAME",
1068 NO_STR "Configure a global list of allowed APNs\n"
1069 "Remove entry with NAME\n")
1070{
1071 struct apn_ctx *apn_ctx = sgsn_apn_ctx_by_name(argv[0], "");
1072 if (!apn_ctx)
1073 return CMD_SUCCESS;
1074
1075 sgsn_apn_ctx_free(apn_ctx);
1076 return CMD_SUCCESS;
1077}
1078
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001079DEFUN(cfg_cdr_filename, cfg_cdr_filename_cmd,
1080 "cdr filename NAME",
1081 "CDR\nSet filename\nname\n")
1082{
1083 talloc_free(g_cfg->cdr.filename);
1084 g_cfg->cdr.filename = talloc_strdup(tall_vty_ctx, argv[0]);
1085 return CMD_SUCCESS;
1086}
1087
1088DEFUN(cfg_no_cdr_filename, cfg_no_cdr_filename_cmd,
1089 "no cdr filename",
1090 NO_STR "CDR\nDisable CDR generation\n")
1091{
1092 talloc_free(g_cfg->cdr.filename);
1093 g_cfg->cdr.filename = NULL;
1094 return CMD_SUCCESS;
1095}
1096
1097DEFUN(cfg_cdr_interval, cfg_cdr_interval_cmd,
1098 "cdr interval <1-2147483647>",
1099 "CDR\nPDP periodic log interval\nSeconds\n")
1100{
1101 g_cfg->cdr.interval = atoi(argv[0]);
1102 return CMD_SUCCESS;
1103}
1104
Philippf1f34362016-08-26 17:00:21 +02001105#define COMPRESSION_STR "Configure compression\n"
1106DEFUN(cfg_no_comp_rfc1144, cfg_no_comp_rfc1144_cmd,
1107 "no compression rfc1144",
1108 NO_STR COMPRESSION_STR "disable rfc1144 TCP/IP header compression\n")
1109{
1110 g_cfg->pcomp_rfc1144.active = 0;
1111 g_cfg->pcomp_rfc1144.passive = 0;
1112 return CMD_SUCCESS;
1113}
1114
1115DEFUN(cfg_comp_rfc1144, cfg_comp_rfc1144_cmd,
1116 "compression rfc1144 active slots <1-256>",
1117 COMPRESSION_STR
1118 "RFC1144 Header compresion scheme\n"
1119 "Compression is actively proposed\n"
1120 "Number of compression state slots\n"
1121 "Number of compression state slots\n")
1122{
1123 g_cfg->pcomp_rfc1144.active = 1;
1124 g_cfg->pcomp_rfc1144.passive = 1;
1125 g_cfg->pcomp_rfc1144.s01 = atoi(argv[0]) - 1;
1126 return CMD_SUCCESS;
1127}
1128
1129DEFUN(cfg_comp_rfc1144p, cfg_comp_rfc1144p_cmd,
1130 "compression rfc1144 passive",
1131 COMPRESSION_STR
1132 "RFC1144 Header compresion scheme\n"
1133 "Compression is available on request\n")
1134{
1135 g_cfg->pcomp_rfc1144.active = 0;
1136 g_cfg->pcomp_rfc1144.passive = 1;
1137 return CMD_SUCCESS;
1138}
1139
Philipp73f83d52016-09-02 13:38:01 +02001140DEFUN(cfg_no_comp_v42bis, cfg_no_comp_v42bis_cmd,
1141 "no compression v42bis",
1142 NO_STR COMPRESSION_STR "disable V.42bis data compression\n")
1143{
1144 g_cfg->dcomp_v42bis.active = 0;
1145 g_cfg->dcomp_v42bis.passive = 0;
1146 return CMD_SUCCESS;
1147}
1148
1149DEFUN(cfg_comp_v42bis, cfg_comp_v42bis_cmd,
1150 "compression v42bis active direction (ms|sgsn|both) codewords <512-65535> strlen <6-250>",
1151 COMPRESSION_STR
1152 "V.42bis data compresion scheme\n"
1153 "Compression is actively proposed\n"
1154 "Direction in which the compression shall be active (p0)\n"
1155 "Compress ms->sgsn direction only\n"
1156 "Compress sgsn->ms direction only\n"
1157 "Both directions\n"
1158 "Number of codewords (p1)\n"
1159 "Number of codewords\n"
1160 "Maximum string length (p2)\n" "Maximum string length\n")
1161{
1162 g_cfg->dcomp_v42bis.active = 1;
1163 g_cfg->dcomp_v42bis.passive = 1;
1164
1165 switch (argv[0][0]) {
1166 case 'm':
1167 g_cfg->dcomp_v42bis.p0 = 1;
1168 break;
1169 case 's':
1170 g_cfg->dcomp_v42bis.p0 = 2;
1171 break;
1172 case 'b':
1173 g_cfg->dcomp_v42bis.p0 = 3;
1174 break;
1175 }
1176
1177 g_cfg->dcomp_v42bis.p1 = atoi(argv[1]);
1178 g_cfg->dcomp_v42bis.p2 = atoi(argv[2]);
1179 return CMD_SUCCESS;
1180}
1181
1182DEFUN(cfg_comp_v42bisp, cfg_comp_v42bisp_cmd,
1183 "compression v42bis passive",
1184 COMPRESSION_STR
1185 "V.42bis data compresion scheme\n"
1186 "Compression is available on request\n")
1187{
1188 g_cfg->dcomp_v42bis.active = 0;
1189 g_cfg->dcomp_v42bis.passive = 1;
1190 return CMD_SUCCESS;
1191}
1192
Harald Welte288be162010-05-01 16:48:27 +02001193int sgsn_vty_init(void)
1194{
Harald Welted193cb32010-05-17 22:58:03 +02001195 install_element_ve(&show_sgsn_cmd);
1196 //install_element_ve(&show_mmctx_tlli_cmd);
1197 install_element_ve(&show_mmctx_imsi_cmd);
1198 install_element_ve(&show_mmctx_all_cmd);
1199 install_element_ve(&show_pdpctx_all_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001200 install_element_ve(&show_subscr_cache_cmd);
1201
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01001202 install_element(ENABLE_NODE, &update_subscr_insert_auth_triplet_cmd);
Jacob Erlbeckd9193432015-01-19 14:11:46 +01001203 install_element(ENABLE_NODE, &update_subscr_create_cmd);
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001204 install_element(ENABLE_NODE, &update_subscr_destroy_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001205 install_element(ENABLE_NODE, &update_subscr_cancel_cmd);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001206 install_element(ENABLE_NODE, &update_subscr_update_location_result_cmd);
1207 install_element(ENABLE_NODE, &update_subscr_update_auth_info_cmd);
Harald Welte288be162010-05-01 16:48:27 +02001208
1209 install_element(CONFIG_NODE, &cfg_sgsn_cmd);
1210 install_node(&sgsn_node, config_write_sgsn);
Jacob Erlbeck36722e12013-10-29 09:30:30 +01001211 vty_install_default(SGSN_NODE);
Harald Weltee300d002010-06-02 12:41:34 +02001212 install_element(SGSN_NODE, &cfg_sgsn_bind_addr_cmd);
Harald Welted193cb32010-05-17 22:58:03 +02001213 install_element(SGSN_NODE, &cfg_ggsn_remote_ip_cmd);
1214 //install_element(SGSN_NODE, &cfg_ggsn_remote_port_cmd);
1215 install_element(SGSN_NODE, &cfg_ggsn_gtp_version_cmd);
Harald Welte7f6da482013-03-19 11:00:13 +01001216 install_element(SGSN_NODE, &cfg_imsi_acl_cmd);
Harald Welte3dfb5492013-03-19 11:48:54 +01001217 install_element(SGSN_NODE, &cfg_auth_policy_cmd);
Max93408ae2016-06-28 14:10:16 +02001218 install_element(SGSN_NODE, &cfg_encrypt_cmd);
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001219 install_element(SGSN_NODE, &cfg_gsup_remote_ip_cmd);
1220 install_element(SGSN_NODE, &cfg_gsup_remote_port_cmd);
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001221 install_element(SGSN_NODE, &cfg_gsup_oap_id_cmd);
1222 install_element(SGSN_NODE, &cfg_gsup_oap_k_cmd);
1223 install_element(SGSN_NODE, &cfg_gsup_oap_opc_cmd);
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +01001224 install_element(SGSN_NODE, &cfg_apn_ggsn_cmd);
1225 install_element(SGSN_NODE, &cfg_apn_imsi_ggsn_cmd);
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001226 install_element(SGSN_NODE, &cfg_apn_name_cmd);
1227 install_element(SGSN_NODE, &cfg_no_apn_name_cmd);
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001228 install_element(SGSN_NODE, &cfg_cdr_filename_cmd);
1229 install_element(SGSN_NODE, &cfg_no_cdr_filename_cmd);
1230 install_element(SGSN_NODE, &cfg_cdr_interval_cmd);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001231 install_element(SGSN_NODE, &cfg_ggsn_dynamic_lookup_cmd);
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +08001232 install_element(SGSN_NODE, &cfg_grx_ggsn_cmd);
Harald Welte288be162010-05-01 16:48:27 +02001233
Harald Welte94508822015-08-15 19:08:21 +02001234 install_element(SGSN_NODE, &cfg_sgsn_T3312_cmd);
1235 install_element(SGSN_NODE, &cfg_sgsn_T3322_cmd);
1236 install_element(SGSN_NODE, &cfg_sgsn_T3350_cmd);
1237 install_element(SGSN_NODE, &cfg_sgsn_T3360_cmd);
1238 install_element(SGSN_NODE, &cfg_sgsn_T3370_cmd);
1239 install_element(SGSN_NODE, &cfg_sgsn_T3313_cmd);
1240 install_element(SGSN_NODE, &cfg_sgsn_T3314_cmd);
1241 install_element(SGSN_NODE, &cfg_sgsn_T3316_cmd);
1242 install_element(SGSN_NODE, &cfg_sgsn_T3385_cmd);
1243 install_element(SGSN_NODE, &cfg_sgsn_T3386_cmd);
1244 install_element(SGSN_NODE, &cfg_sgsn_T3395_cmd);
1245 install_element(SGSN_NODE, &cfg_sgsn_T3397_cmd);
1246
Philippf1f34362016-08-26 17:00:21 +02001247 install_element(SGSN_NODE, &cfg_no_comp_rfc1144_cmd);
1248 install_element(SGSN_NODE, &cfg_comp_rfc1144_cmd);
1249 install_element(SGSN_NODE, &cfg_comp_rfc1144p_cmd);
Philipp73f83d52016-09-02 13:38:01 +02001250 install_element(SGSN_NODE, &cfg_no_comp_v42bis_cmd);
1251 install_element(SGSN_NODE, &cfg_comp_v42bis_cmd);
1252 install_element(SGSN_NODE, &cfg_comp_v42bisp_cmd);
Harald Welte288be162010-05-01 16:48:27 +02001253 return 0;
1254}
1255
1256int sgsn_parse_config(const char *config_file, struct sgsn_config *cfg)
1257{
1258 int rc;
1259
1260 g_cfg = cfg;
Harald Welte7f6da482013-03-19 11:00:13 +01001261
Harald Welte94508822015-08-15 19:08:21 +02001262 g_cfg->timers.T3312 = GSM0408_T3312_SECS;
1263 g_cfg->timers.T3322 = GSM0408_T3322_SECS;
1264 g_cfg->timers.T3350 = GSM0408_T3350_SECS;
1265 g_cfg->timers.T3360 = GSM0408_T3360_SECS;
1266 g_cfg->timers.T3370 = GSM0408_T3370_SECS;
1267 g_cfg->timers.T3313 = GSM0408_T3313_SECS;
1268 g_cfg->timers.T3314 = GSM0408_T3314_SECS;
1269 g_cfg->timers.T3316 = GSM0408_T3316_SECS;
1270 g_cfg->timers.T3385 = GSM0408_T3385_SECS;
1271 g_cfg->timers.T3386 = GSM0408_T3386_SECS;
1272 g_cfg->timers.T3395 = GSM0408_T3395_SECS;
1273 g_cfg->timers.T3397 = GSM0408_T3397_SECS;
1274
Harald Weltedcccb182010-05-16 20:52:23 +02001275 rc = vty_read_config_file(config_file, NULL);
Harald Welte288be162010-05-01 16:48:27 +02001276 if (rc < 0) {
1277 fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
1278 return rc;
1279 }
1280
1281 return 0;
1282}