blob: 65b5a39e196e4f336a41eaccac64a21fe5e2676d [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 Welte288be162010-05-01 16:48:27 +020030
31#include <openbsc/debug.h>
32#include <openbsc/sgsn.h>
Harald Welteea34a4e2012-06-16 14:59:56 +080033#include <osmocom/gprs/gprs_ns.h>
Harald Welted193cb32010-05-17 22:58:03 +020034#include <openbsc/gprs_sgsn.h>
Harald Welte62ab20c2010-05-14 18:59:17 +020035#include <openbsc/vty.h>
Harald Weltec5d4a0c2010-07-02 22:47:59 +020036#include <openbsc/gsm_04_08_gprs.h>
Jacob Erlbeck80547992014-12-19 19:19:46 +010037#include <openbsc/gprs_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>
Harald Welte288be162010-05-01 16:48:27 +020042
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
57
Harald Weltec5d4a0c2010-07-02 22:47:59 +020058#define GSM48_MAX_APN_LEN 102 /* 10.5.6.1 */
59static char *gprs_apn2str(uint8_t *apn, unsigned int len)
60{
61 static char apnbuf[GSM48_MAX_APN_LEN+1];
Holger Hans Peter Freyther80e03652013-07-04 18:44:16 +020062 unsigned int i = 0;
Harald Weltec5d4a0c2010-07-02 22:47:59 +020063
64 if (!apn)
65 return "";
66
67 if (len > sizeof(apnbuf)-1)
68 len = sizeof(apnbuf)-1;
69
70 memcpy(apnbuf, apn, len);
71 apnbuf[len] = '\0';
72
73 /* replace the domain name step sizes with dots */
74 while (i < len) {
75 unsigned int step = apnbuf[i];
76 apnbuf[i] = '.';
77 i += step+1;
78 }
79
80 return apnbuf+1;
81}
82
Holger Hans Peter Freythera2730302014-03-23 18:08:26 +010083char *gprs_pdpaddr2str(uint8_t *pdpa, uint8_t len)
Harald Weltec5d4a0c2010-07-02 22:47:59 +020084{
85 static char str[INET6_ADDRSTRLEN + 10];
86
87 if (!pdpa || len < 2)
88 return "none";
89
90 switch (pdpa[0] & 0x0f) {
91 case PDP_TYPE_ORG_IETF:
92 switch (pdpa[1]) {
93 case PDP_TYPE_N_IETF_IPv4:
94 if (len < 2 + 4)
95 break;
96 strcpy(str, "IPv4 ");
97 inet_ntop(AF_INET, pdpa+2, str+5, sizeof(str)-5);
98 return str;
99 case PDP_TYPE_N_IETF_IPv6:
100 if (len < 2 + 8)
101 break;
102 strcpy(str, "IPv6 ");
103 inet_ntop(AF_INET6, pdpa+2, str+5, sizeof(str)-5);
104 return str;
105 default:
106 break;
107 }
108 break;
109 case PDP_TYPE_ORG_ETSI:
110 if (pdpa[1] == PDP_TYPE_N_ETSI_PPP)
111 return "PPP";
112 break;
113 default:
114 break;
115 }
116
117 return "invalid";
118}
119
Harald Welte288be162010-05-01 16:48:27 +0200120static struct cmd_node sgsn_node = {
121 SGSN_NODE,
Harald Welte570ce242012-08-17 13:16:10 +0200122 "%s(config-sgsn)# ",
Harald Welte288be162010-05-01 16:48:27 +0200123 1,
124};
125
126static int config_write_sgsn(struct vty *vty)
127{
Harald Welte77289c22010-05-18 14:32:29 +0200128 struct sgsn_ggsn_ctx *gctx;
Harald Welte7f6da482013-03-19 11:00:13 +0100129 struct imsi_acl_entry *acl;
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100130 struct apn_ctx *actx;
Harald Welte288be162010-05-01 16:48:27 +0200131
132 vty_out(vty, "sgsn%s", VTY_NEWLINE);
133
Harald Weltee300d002010-06-02 12:41:34 +0200134 vty_out(vty, " gtp local-ip %s%s",
135 inet_ntoa(g_cfg->gtp_listenaddr.sin_addr), VTY_NEWLINE);
136
Harald Welted193cb32010-05-17 22:58:03 +0200137 llist_for_each_entry(gctx, &sgsn_ggsn_ctxts, list) {
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800138 if (gctx->id == UINT32_MAX)
139 continue;
140
Harald Welteff3bde82010-05-19 15:09:09 +0200141 vty_out(vty, " ggsn %u remote-ip %s%s", gctx->id,
Harald Welted193cb32010-05-17 22:58:03 +0200142 inet_ntoa(gctx->remote_addr), VTY_NEWLINE);
Harald Welteff3bde82010-05-19 15:09:09 +0200143 vty_out(vty, " ggsn %u gtp-version %u%s", gctx->id,
Harald Welted193cb32010-05-17 22:58:03 +0200144 gctx->gtp_version, VTY_NEWLINE);
Harald Welte288be162010-05-01 16:48:27 +0200145 }
146
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800147 if (sgsn->cfg.dynamic_lookup)
148 vty_out(vty, " ggsn dynamic%s", VTY_NEWLINE);
149
Harald Welte3dfb5492013-03-19 11:48:54 +0100150 vty_out(vty, " auth-policy %s%s",
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100151 get_value_string(sgsn_auth_pol_strs, g_cfg->auth_policy),
152 VTY_NEWLINE);
Jacob Erlbeck39f040d2014-12-18 12:46:47 +0100153 if (g_cfg->gsup_server_addr.sin_addr.s_addr)
154 vty_out(vty, " gsup remote-ip %s%s",
155 inet_ntoa(g_cfg->gsup_server_addr.sin_addr), VTY_NEWLINE);
156 if (g_cfg->gsup_server_port)
157 vty_out(vty, " gsup remote-port %d%s",
158 g_cfg->gsup_server_port, VTY_NEWLINE);
Harald Welte7f6da482013-03-19 11:00:13 +0100159 llist_for_each_entry(acl, &g_cfg->imsi_acl, list)
160 vty_out(vty, " imsi-acl add %s%s", acl->imsi, VTY_NEWLINE);
161
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100162 if (llist_empty(&sgsn_apn_ctxts))
163 vty_out(vty, " ! apn * ggsn 0%s", VTY_NEWLINE);
164 llist_for_each_entry(actx, &sgsn_apn_ctxts, list) {
165 if (strlen(actx->imsi_prefix) > 0)
166 vty_out(vty, " apn %s imsi-prefix %s ggsn %d%s",
167 actx->name, actx->imsi_prefix, actx->ggsn->id,
168 VTY_NEWLINE);
169 else
170 vty_out(vty, " apn %s ggsn %d%s", actx->name,
171 actx->ggsn->id, VTY_NEWLINE);
172 }
173
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +0200174 if (g_cfg->cdr.filename)
175 vty_out(vty, " cdr filename %s%s", g_cfg->cdr.filename, VTY_NEWLINE);
176 else
177 vty_out(vty, " no cdr filename%s", VTY_NEWLINE);
178 vty_out(vty, " cdr interval %d%s", g_cfg->cdr.interval, VTY_NEWLINE);
179
Harald Welte288be162010-05-01 16:48:27 +0200180 return CMD_SUCCESS;
181}
182
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100183#define SGSN_STR "Configure the SGSN\n"
184#define GGSN_STR "Configure the GGSN information\n"
Harald Weltee300d002010-06-02 12:41:34 +0200185
186DEFUN(cfg_sgsn, cfg_sgsn_cmd,
187 "sgsn",
188 SGSN_STR)
Harald Welte288be162010-05-01 16:48:27 +0200189{
190 vty->node = SGSN_NODE;
191 return CMD_SUCCESS;
192}
193
Harald Weltee300d002010-06-02 12:41:34 +0200194DEFUN(cfg_sgsn_bind_addr, cfg_sgsn_bind_addr_cmd,
195 "gtp local-ip A.B.C.D",
196 "GTP Parameters\n"
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100197 "Set the IP address for the local GTP bind\n"
198 "IPv4 Address\n")
Harald Weltee300d002010-06-02 12:41:34 +0200199{
200 inet_aton(argv[0], &g_cfg->gtp_listenaddr.sin_addr);
201
202 return CMD_SUCCESS;
203}
204
Harald Welted193cb32010-05-17 22:58:03 +0200205DEFUN(cfg_ggsn_remote_ip, cfg_ggsn_remote_ip_cmd,
206 "ggsn <0-255> remote-ip A.B.C.D",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100207 GGSN_STR "GGSN Number\n" IP_STR "IPv4 Address\n")
Harald Welted193cb32010-05-17 22:58:03 +0200208{
209 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200210 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welte288be162010-05-01 16:48:27 +0200211
Harald Welted193cb32010-05-17 22:58:03 +0200212 inet_aton(argv[1], &ggc->remote_addr);
Harald Welte288be162010-05-01 16:48:27 +0200213
Harald Welted193cb32010-05-17 22:58:03 +0200214 return CMD_SUCCESS;
215}
216
217#if 0
218DEFUN(cfg_ggsn_remote_port, cfg_ggsn_remote_port_cmd,
219 "ggsn <0-255> remote-port <0-65535>",
220 "")
221{
222 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200223 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welted193cb32010-05-17 22:58:03 +0200224 uint16_t port = atoi(argv[1]);
225
226}
227#endif
228
229DEFUN(cfg_ggsn_gtp_version, cfg_ggsn_gtp_version_cmd,
230 "ggsn <0-255> gtp-version (0|1)",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100231 GGSN_STR "GGSN Number\n" "GTP Version\n"
232 "Version 0\n" "Version 1\n")
Harald Welted193cb32010-05-17 22:58:03 +0200233{
234 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200235 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welted193cb32010-05-17 22:58:03 +0200236
237 if (atoi(argv[1]))
238 ggc->gtp_version = 1;
239 else
240 ggc->gtp_version = 0;
241
242 return CMD_SUCCESS;
243}
244
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800245DEFUN(cfg_ggsn_dynamic_lookup, cfg_ggsn_dynamic_lookup_cmd,
246 "ggsn dynamic",
247 GGSN_STR "Enable dynamic GRX based look-up (requires restart)\n")
248{
249 sgsn->cfg.dynamic_lookup = 1;
250 return CMD_SUCCESS;
251}
252
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100253#define APN_STR "Configure the information per APN\n"
254#define APN_GW_STR "The APN gateway name optionally prefixed by '*' (wildcard)\n"
255
256static int add_apn_ggsn_mapping(struct vty *vty, const char *apn_str,
257 const char *imsi_prefix, int ggsn_id)
258{
259 struct apn_ctx *actx;
260 struct sgsn_ggsn_ctx *ggsn;
261
262 ggsn = sgsn_ggsn_ctx_by_id(ggsn_id);
263 if (ggsn == NULL) {
264 vty_out(vty, "%% a GGSN with id %d has not been defined%s",
265 ggsn_id, VTY_NEWLINE);
266 return CMD_WARNING;
267 }
268
269 actx = sgsn_apn_ctx_find_alloc(apn_str, imsi_prefix);
270 if (!actx) {
271 vty_out(vty, "%% unable to create APN context for %s/%s%s",
272 apn_str, imsi_prefix, VTY_NEWLINE);
273 return CMD_WARNING;
274 }
275
276 actx->ggsn = ggsn;
277
278 return CMD_SUCCESS;
279}
280
Harald Welted193cb32010-05-17 22:58:03 +0200281DEFUN(cfg_apn_ggsn, cfg_apn_ggsn_cmd,
282 "apn APNAME ggsn <0-255>",
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100283 APN_STR APN_GW_STR
284 "Select the GGSN to use when the APN gateway prefix matches\n"
285 "The GGSN id")
Harald Welted193cb32010-05-17 22:58:03 +0200286{
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100287
288 return add_apn_ggsn_mapping(vty, argv[0], "", atoi(argv[1]));
Harald Welted193cb32010-05-17 22:58:03 +0200289}
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100290
291DEFUN(cfg_apn_imsi_ggsn, cfg_apn_imsi_ggsn_cmd,
292 "apn APNAME imsi-prefix IMSIPRE ggsn <0-255>",
293 APN_STR APN_GW_STR
294 "Restrict rule to a certain IMSI prefix\n"
295 "An IMSI prefix\n"
296 "Select the GGSN to use when APN gateway and IMSI prefix match\n"
297 "The GGSN id")
298{
299
300 return add_apn_ggsn_mapping(vty, argv[0], argv[1], atoi(argv[2]));
301}
Harald Welted193cb32010-05-17 22:58:03 +0200302
303const struct value_string gprs_mm_st_strs[] = {
304 { GMM_DEREGISTERED, "DEREGISTERED" },
305 { GMM_COMMON_PROC_INIT, "COMMON PROCEDURE (INIT)" },
306 { GMM_REGISTERED_NORMAL, "REGISTERED (NORMAL)" },
Harald Weltebffeff82010-06-09 15:50:45 +0200307 { GMM_REGISTERED_SUSPENDED, "REGISTERED (SUSPENDED)" },
Harald Welted193cb32010-05-17 22:58:03 +0200308 { GMM_DEREGISTERED_INIT, "DEREGISTERED (INIT)" },
309 { 0, NULL }
310};
311
312static void vty_dump_pdp(struct vty *vty, const char *pfx,
313 struct sgsn_pdp_ctx *pdp)
314{
Jacob Erlbeck99985b52014-10-13 10:32:00 +0200315 const char *imsi = pdp->mm ? pdp->mm->imsi : "(detaching)";
Harald Welted193cb32010-05-17 22:58:03 +0200316 vty_out(vty, "%sPDP Context IMSI: %s, SAPI: %u, NSAPI: %u%s",
Jacob Erlbeck99985b52014-10-13 10:32:00 +0200317 pfx, imsi, pdp->sapi, pdp->nsapi, VTY_NEWLINE);
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200318 vty_out(vty, "%s APN: %s%s", pfx,
319 gprs_apn2str(pdp->lib->apn_use.v, pdp->lib->apn_use.l),
320 VTY_NEWLINE);
321 vty_out(vty, "%s PDP Address: %s%s", pfx,
322 gprs_pdpaddr2str(pdp->lib->eua.v, pdp->lib->eua.l),
323 VTY_NEWLINE);
Harald Welteefbdee92010-06-10 00:20:12 +0200324 vty_out_rate_ctr_group(vty, " ", pdp->ctrg);
Harald Welted193cb32010-05-17 22:58:03 +0200325}
326
327static void vty_dump_mmctx(struct vty *vty, const char *pfx,
328 struct sgsn_mm_ctx *mm, int pdp)
329{
330 vty_out(vty, "%sMM Context for IMSI %s, IMEI %s, P-TMSI %08x%s",
331 pfx, mm->imsi, mm->imei, mm->p_tmsi, VTY_NEWLINE);
Holger Hans Peter Freyther8ee13e22015-05-18 10:00:03 +0200332 vty_out(vty, "%s MSISDN: %s, TLLI: %08x%s HLR: %s",
333 pfx, mm->msisdn, mm->tlli, mm->hlr, VTY_NEWLINE);
Harald Welted193cb32010-05-17 22:58:03 +0200334 vty_out(vty, "%s MM State: %s, Routeing Area: %u-%u-%u-%u, "
335 "Cell ID: %u%s", pfx,
336 get_value_string(gprs_mm_st_strs, mm->mm_state),
337 mm->ra.mcc, mm->ra.mnc, mm->ra.lac, mm->ra.rac,
338 mm->cell_id, VTY_NEWLINE);
339
Harald Welte8acd88f2010-05-18 10:57:45 +0200340 vty_out_rate_ctr_group(vty, " ", mm->ctrg);
341
Harald Welted193cb32010-05-17 22:58:03 +0200342 if (pdp) {
343 struct sgsn_pdp_ctx *pdp;
344
345 llist_for_each_entry(pdp, &mm->pdp_list, list)
346 vty_dump_pdp(vty, " ", pdp);
347 }
348}
349
350DEFUN(show_sgsn, show_sgsn_cmd, "show sgsn",
351 SHOW_STR "Display information about the SGSN")
352{
Jacob Erlbeck80547992014-12-19 19:19:46 +0100353 if (sgsn->gsup_client) {
354 struct ipa_client_conn *link = sgsn->gsup_client->link;
355 vty_out(vty,
356 " Remote authorization: %sconnected to %s:%d via GSUP%s",
357 sgsn->gsup_client->is_connected ? "" : "not ",
358 link->addr, link->port,
359 VTY_NEWLINE);
360 }
Harald Welted193cb32010-05-17 22:58:03 +0200361 /* FIXME: statistics */
362 return CMD_SUCCESS;
363}
364
365#define MMCTX_STR "MM Context\n"
366#define INCLUDE_PDP_STR "Include PDP Context Information\n"
367
368#if 0
369DEFUN(show_mmctx_tlli, show_mmctx_tlli_cmd,
370 "show mm-context tlli HEX [pdp]",
371 SHOW_STR MMCTX_STR "Identify by TLLI\n" "TLLI\n" INCLUDE_PDP_STR)
372{
373 uint32_t tlli;
374 struct sgsn_mm_ctx *mm;
375
376 tlli = strtoul(argv[0], NULL, 16);
377 mm = sgsn_mm_ctx_by_tlli(tlli);
378 if (!mm) {
379 vty_out(vty, "No MM context for TLLI %08x%s",
380 tlli, VTY_NEWLINE);
381 return CMD_WARNING;
382 }
383 vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
384 return CMD_SUCCESS;
385}
386#endif
387
388DEFUN(swow_mmctx_imsi, show_mmctx_imsi_cmd,
389 "show mm-context imsi IMSI [pdp]",
390 SHOW_STR MMCTX_STR "Identify by IMSI\n" "IMSI of the MM Context\n"
391 INCLUDE_PDP_STR)
392{
393 struct sgsn_mm_ctx *mm;
394
395 mm = sgsn_mm_ctx_by_imsi(argv[0]);
396 if (!mm) {
397 vty_out(vty, "No MM context for IMSI %s%s",
398 argv[0], VTY_NEWLINE);
399 return CMD_WARNING;
400 }
401 vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
402 return CMD_SUCCESS;
403}
404
405DEFUN(swow_mmctx_all, show_mmctx_all_cmd,
406 "show mm-context all [pdp]",
407 SHOW_STR MMCTX_STR "All MM Contexts\n" INCLUDE_PDP_STR)
408{
409 struct sgsn_mm_ctx *mm;
410
411 llist_for_each_entry(mm, &sgsn_mm_ctxts, list)
412 vty_dump_mmctx(vty, "", mm, argv[0] ? 1 : 0);
413
414 return CMD_SUCCESS;
415}
416
Harald Welted193cb32010-05-17 22:58:03 +0200417DEFUN(show_pdpctx_all, show_pdpctx_all_cmd,
418 "show pdp-context all",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100419 SHOW_STR "Display information on PDP Context\n" "Show everything\n")
Harald Welted193cb32010-05-17 22:58:03 +0200420{
421 struct sgsn_pdp_ctx *pdp;
422
423 llist_for_each_entry(pdp, &sgsn_pdp_ctxts, g_list)
424 vty_dump_pdp(vty, "", pdp);
425
426 return CMD_SUCCESS;
427}
Harald Welte288be162010-05-01 16:48:27 +0200428
Harald Welte7f6da482013-03-19 11:00:13 +0100429
430DEFUN(imsi_acl, cfg_imsi_acl_cmd,
431 "imsi-acl (add|del) IMSI",
432 "Access Control List of foreign IMSIs\n"
433 "Add IMSI to ACL\n"
434 "Remove IMSI from ACL\n"
435 "IMSI of subscriber\n")
436{
437 const char *op = argv[0];
438 const char *imsi = argv[1];
439 int rc;
440
441 if (!strcmp(op, "add"))
Jacob Erlbeck3b5d4072014-10-24 15:11:03 +0200442 rc = sgsn_acl_add(imsi, g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +0100443 else
Jacob Erlbeck3b5d4072014-10-24 15:11:03 +0200444 rc = sgsn_acl_del(imsi, g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +0100445
446 if (rc < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100447 vty_out(vty, "%% unable to %s ACL%s", op, VTY_NEWLINE);
448
Harald Welte7f6da482013-03-19 11:00:13 +0100449 return CMD_WARNING;
450 }
451
452 return CMD_SUCCESS;
453}
454
Harald Welte3dfb5492013-03-19 11:48:54 +0100455DEFUN(cfg_auth_policy, cfg_auth_policy_cmd,
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100456 "auth-policy (accept-all|closed|acl-only|remote)",
Harald Welte3dfb5492013-03-19 11:48:54 +0100457 "Autorization Policy of SGSN\n"
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100458 "Accept all IMSIs (DANGEROUS)\n"
459 "Accept only home network subscribers or those in the ACL\n"
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100460 "Accept only subscribers in the ACL\n"
461 "Use remote subscription data only (HLR)\n")
Harald Welte3dfb5492013-03-19 11:48:54 +0100462{
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100463 int val = get_string_value(sgsn_auth_pol_strs, argv[0]);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100464 OSMO_ASSERT(val >= SGSN_AUTH_POLICY_OPEN && val <= SGSN_AUTH_POLICY_REMOTE);
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100465 g_cfg->auth_policy = val;
Jacob Erlbeck9d4f46c2014-12-17 13:20:08 +0100466 g_cfg->require_authentication = (val == SGSN_AUTH_POLICY_REMOTE);
Jacob Erlbeck771573c2014-12-19 18:08:48 +0100467 g_cfg->require_update_location = (val == SGSN_AUTH_POLICY_REMOTE);
Harald Welte3dfb5492013-03-19 11:48:54 +0100468
469 return CMD_SUCCESS;
470}
471
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100472/* Subscriber */
473#include <openbsc/gsm_subscriber.h>
474
475static void subscr_dump_full_vty(struct vty *vty, struct gsm_subscriber *subscr, int pending)
476{
477 char expire_time[200];
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100478 struct gsm_auth_tuple *at;
479 int at_idx;
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100480 struct sgsn_subscriber_pdp_data *pdp;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100481
482 vty_out(vty, " ID: %llu, Authorized: %d%s", subscr->id,
483 subscr->authorized, VTY_NEWLINE);
484 if (strlen(subscr->name))
485 vty_out(vty, " Name: '%s'%s", subscr->name, VTY_NEWLINE);
486 if (strlen(subscr->extension))
487 vty_out(vty, " Extension: %s%s", subscr->extension,
488 VTY_NEWLINE);
489 vty_out(vty, " LAC: %d/0x%x%s",
490 subscr->lac, subscr->lac, VTY_NEWLINE);
491 vty_out(vty, " IMSI: %s%s", subscr->imsi, VTY_NEWLINE);
492 if (subscr->tmsi != GSM_RESERVED_TMSI)
493 vty_out(vty, " TMSI: %08X%s", subscr->tmsi,
494 VTY_NEWLINE);
Holger Hans Peter Freytherf7b38262015-04-23 16:58:33 -0400495 if (subscr->sgsn_data->msisdn_len > 0)
496 vty_out(vty, " MSISDN (BCD): %s%s",
497 osmo_hexdump(subscr->sgsn_data->msisdn,
498 subscr->sgsn_data->msisdn_len),
499 VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100500
501 if (strlen(subscr->equipment.imei) > 0)
502 vty_out(vty, " IMEI: %s%s", subscr->equipment.imei, VTY_NEWLINE);
503
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100504 for (at_idx = 0; at_idx < ARRAY_SIZE(subscr->sgsn_data->auth_triplets);
505 at_idx++) {
506 at = &subscr->sgsn_data->auth_triplets[at_idx];
507 if (at->key_seq == GSM_KEY_SEQ_INVAL)
508 continue;
509
510 vty_out(vty, " A3A8 tuple (used %d times): ",
511 at->use_count);
512 vty_out(vty, " seq # : %d, ",
513 at->key_seq);
514 vty_out(vty, " RAND : %s, ",
515 osmo_hexdump(at->rand, sizeof(at->rand)));
516 vty_out(vty, " SRES : %s, ",
517 osmo_hexdump(at->sres, sizeof(at->sres)));
518 vty_out(vty, " Kc : %s%s",
519 osmo_hexdump(at->kc, sizeof(at->kc)),
520 VTY_NEWLINE);
521 }
522
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100523 llist_for_each_entry(pdp, &subscr->sgsn_data->pdp_list, list) {
Holger Hans Peter Freytherd05e0692015-04-23 16:59:04 -0400524 vty_out(vty, " PDP info: Id: %d, Type: 0x%04x, APN: '%s' QoS: %s%s",
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100525 pdp->context_id, pdp->pdp_type, pdp->apn_str,
Holger Hans Peter Freytherd05e0692015-04-23 16:59:04 -0400526 osmo_hexdump(pdp->qos_subscribed, pdp->qos_subscribed_len),
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100527 VTY_NEWLINE);
528 }
529
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100530 /* print the expiration time of a subscriber */
531 if (subscr->expire_lu) {
532 strftime(expire_time, sizeof(expire_time),
533 "%a, %d %b %Y %T %z", localtime(&subscr->expire_lu));
534 expire_time[sizeof(expire_time) - 1] = '\0';
535 vty_out(vty, " Expiration Time: %s%s", expire_time, VTY_NEWLINE);
536 }
537
538 if (subscr->flags)
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100539 vty_out(vty, " Flags: %s%s%s%s%s%s",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100540 subscr->flags & GSM_SUBSCRIBER_FIRST_CONTACT ?
541 "FIRST_CONTACT " : "",
542 subscr->flags & GPRS_SUBSCRIBER_CANCELLED ?
543 "CANCELLED " : "",
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100544 subscr->flags & GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING ?
545 "UPDATE_LOCATION_PENDING " : "",
546 subscr->flags & GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING ?
547 "AUTH_INFO_PENDING " : "",
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100548 subscr->flags & GPRS_SUBSCRIBER_ENABLE_PURGE ?
549 "ENABLE_PURGE " : "",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100550 VTY_NEWLINE);
551
552 vty_out(vty, " Use count: %u%s", subscr->use_count, VTY_NEWLINE);
553}
554
555DEFUN(show_subscr_cache,
556 show_subscr_cache_cmd,
557 "show subscriber cache",
558 SHOW_STR "Show information about subscribers\n"
559 "Display contents of subscriber cache\n")
560{
561 struct gsm_subscriber *subscr;
562
563 llist_for_each_entry(subscr, &active_subscribers, entry) {
564 vty_out(vty, " Subscriber:%s", VTY_NEWLINE);
565 subscr_dump_full_vty(vty, subscr, 0);
566 }
567
568 return CMD_SUCCESS;
569}
570
571#define UPDATE_SUBSCR_STR "update-subscriber imsi IMSI "
572#define UPDATE_SUBSCR_HELP "Update subscriber list\n" \
573 "Use the IMSI to select the subscriber\n" \
574 "The IMSI\n"
575
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100576#define UPDATE_SUBSCR_INSERT_HELP "Insert data into the subscriber record\n"
577
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100578DEFUN(update_subscr_insert_auth_triplet, update_subscr_insert_auth_triplet_cmd,
579 UPDATE_SUBSCR_STR "insert auth-triplet <1-5> sres SRES rand RAND kc KC",
580 UPDATE_SUBSCR_HELP
581 UPDATE_SUBSCR_INSERT_HELP
582 "Update authentication triplet\n"
583 "Triplet index\n"
584 "Set SRES value\nSRES value (4 byte) in hex\n"
585 "Set RAND value\nRAND value (16 byte) in hex\n"
586 "Set Kc value\nKc value (8 byte) in hex\n")
587{
588 const char *imsi = argv[0];
589 const int cksn = atoi(argv[1]) - 1;
590 const char *sres_str = argv[2];
591 const char *rand_str = argv[3];
592 const char *kc_str = argv[4];
593 struct gsm_auth_tuple at = {0,};
594
595 struct gsm_subscriber *subscr;
596
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100597 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100598 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100599 vty_out(vty, "%% unable get subscriber record for %s%s",
600 imsi, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100601 return CMD_WARNING;
602 }
603
604 OSMO_ASSERT(subscr->sgsn_data);
605
Jacob Erlbeck17fb3d42015-01-05 09:43:51 +0100606 if (osmo_hexparse(sres_str, &at.sres[0], sizeof(at.sres)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100607 vty_out(vty, "%% invalid SRES value '%s'%s",
608 sres_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100609 goto failed;
610 }
Jacob Erlbeck17fb3d42015-01-05 09:43:51 +0100611 if (osmo_hexparse(rand_str, &at.rand[0], sizeof(at.rand)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100612 vty_out(vty, "%% invalid RAND value '%s'%s",
613 rand_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100614 goto failed;
615 }
Jacob Erlbeck17fb3d42015-01-05 09:43:51 +0100616 if (osmo_hexparse(kc_str, &at.kc[0], sizeof(at.kc)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100617 vty_out(vty, "%% invalid Kc value '%s'%s",
618 kc_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100619 goto failed;
620 }
621 at.key_seq = cksn;
622
623 subscr->sgsn_data->auth_triplets[cksn] = at;
624 subscr->sgsn_data->auth_triplets_updated = 1;
625
626 subscr_put(subscr);
627
628 return CMD_SUCCESS;
629
630failed:
631 subscr_put(subscr);
632 return CMD_SUCCESS;
633}
634
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100635DEFUN(update_subscr_cancel, update_subscr_cancel_cmd,
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100636 UPDATE_SUBSCR_STR "cancel (update-procedure|subscription-withdraw)",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100637 UPDATE_SUBSCR_HELP
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100638 "Cancel (remove) subscriber record\n"
639 "The MS moved to another SGSN\n"
640 "The subscription is no longer valid\n")
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100641{
642 const char *imsi = argv[0];
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100643 const char *cancel_type = argv[1];
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100644
645 struct gsm_subscriber *subscr;
646
647 subscr = gprs_subscr_get_by_imsi(imsi);
648 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100649 vty_out(vty, "%% no subscriber record for %s%s",
650 imsi, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100651 return CMD_WARNING;
652 }
653
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100654 if (strcmp(cancel_type, "update-procedure") == 0)
655 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
656 else
657 subscr->sgsn_data->error_cause = GMM_CAUSE_IMPL_DETACHED;
658
Jacob Erlbeck37139e52015-01-23 13:52:55 +0100659 gprs_subscr_cancel(subscr);
660 subscr_put(subscr);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100661
662 return CMD_SUCCESS;
663}
664
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100665DEFUN(update_subscr_create, update_subscr_create_cmd,
666 UPDATE_SUBSCR_STR "create",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100667 UPDATE_SUBSCR_HELP
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100668 "Create a subscriber entry\n")
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100669{
670 const char *imsi = argv[0];
671
672 struct gsm_subscriber *subscr;
673
674 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100675 if (subscr) {
676 vty_out(vty, "%% subscriber record already exists for %s%s",
677 imsi, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100678 return CMD_WARNING;
679 }
680
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100681 subscr = gprs_subscr_get_or_create(imsi);
682 subscr->keep_in_ram = 1;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100683 subscr_put(subscr);
684
685 return CMD_SUCCESS;
686}
687
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100688DEFUN(update_subscr_destroy, update_subscr_destroy_cmd,
689 UPDATE_SUBSCR_STR "destroy",
690 UPDATE_SUBSCR_HELP
691 "Destroy a subscriber entry\n")
692{
693 const char *imsi = argv[0];
694
695 struct gsm_subscriber *subscr;
696
697 subscr = gprs_subscr_get_by_imsi(imsi);
698 if (!subscr) {
699 vty_out(vty, "%% subscriber record does not exist for %s%s",
700 imsi, VTY_NEWLINE);
701 return CMD_WARNING;
702 }
703
704 subscr->keep_in_ram = 0;
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100705 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100706 gprs_subscr_cancel(subscr);
707 if (subscr->use_count > 1)
708 vty_out(vty, "%% subscriber is still in use%s",
709 VTY_NEWLINE);
710 subscr_put(subscr);
711
712 return CMD_SUCCESS;
713}
714
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100715#define UL_ERR_STR "system-failure|data-missing|unexpected-data-value|" \
716 "unknown-subscriber|roaming-not-allowed"
717
718#define UL_ERR_HELP \
719 "Force error code SystemFailure\n" \
720 "Force error code DataMissing\n" \
721 "Force error code UnexpectedDataValue\n" \
722 "Force error code UnknownSubscriber\n" \
723 "Force error code RoamingNotAllowed\n"
724
725DEFUN(update_subscr_update_location_result, update_subscr_update_location_result_cmd,
726 UPDATE_SUBSCR_STR "update-location-result (ok|" UL_ERR_STR ")",
727 UPDATE_SUBSCR_HELP
728 "Complete the update location procedure\n"
729 "The update location request succeeded\n"
730 UL_ERR_HELP)
731{
732 const char *imsi = argv[0];
733 const char *ret_code_str = argv[1];
734
735 struct gsm_subscriber *subscr;
736
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100737 const struct value_string cause_mapping[] = {
738 { GMM_CAUSE_NET_FAIL, "system-failure" },
739 { GMM_CAUSE_INV_MAND_INFO, "data-missing" },
740 { GMM_CAUSE_PROTO_ERR_UNSPEC, "unexpected-data-value" },
741 { GMM_CAUSE_IMSI_UNKNOWN, "unknown-subscriber" },
742 { GMM_CAUSE_GPRS_NOTALLOWED, "roaming-not-allowed" },
743 { 0, NULL }
744 };
745
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100746 subscr = gprs_subscr_get_by_imsi(imsi);
747 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100748 vty_out(vty, "%% unable to get subscriber record for %s%s",
749 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100750 return CMD_WARNING;
751 }
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100752
753 if (strcmp(ret_code_str, "ok") == 0) {
754 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100755 subscr->authorized = 1;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100756 } else {
757 subscr->sgsn_data->error_cause =
758 get_string_value(cause_mapping, ret_code_str);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100759 subscr->authorized = 0;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100760 }
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100761
762 gprs_subscr_update(subscr);
763
764 subscr_put(subscr);
765
766 return CMD_SUCCESS;
767}
768
769DEFUN(update_subscr_update_auth_info, update_subscr_update_auth_info_cmd,
770 UPDATE_SUBSCR_STR "update-auth-info",
771 UPDATE_SUBSCR_HELP
772 "Complete the send authentication info procedure\n")
773{
774 const char *imsi = argv[0];
775
776 struct gsm_subscriber *subscr;
777
778 subscr = gprs_subscr_get_by_imsi(imsi);
779 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100780 vty_out(vty, "%% unable to get subscriber record for %s%s",
781 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100782 return CMD_WARNING;
783 }
784
785 gprs_subscr_update_auth_info(subscr);
786
787 subscr_put(subscr);
788
789 return CMD_SUCCESS;
790}
791
Jacob Erlbeck39f040d2014-12-18 12:46:47 +0100792DEFUN(cfg_gsup_remote_ip, cfg_gsup_remote_ip_cmd,
793 "gsup remote-ip A.B.C.D",
794 "GSUP Parameters\n"
795 "Set the IP address of the remote GSUP server\n"
796 "IPv4 Address\n")
797{
798 inet_aton(argv[0], &g_cfg->gsup_server_addr.sin_addr);
799
800 return CMD_SUCCESS;
801}
802
803DEFUN(cfg_gsup_remote_port, cfg_gsup_remote_port_cmd,
804 "gsup remote-port <0-65535>",
805 "GSUP Parameters\n"
806 "Set the TCP port of the remote GSUP server\n"
807 "Remote TCP port\n")
808{
809 g_cfg->gsup_server_port = atoi(argv[0]);
810
811 return CMD_SUCCESS;
812}
813
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +0100814DEFUN(cfg_apn_name, cfg_apn_name_cmd,
815 "access-point-name NAME",
816 "Configure a global list of allowed APNs\n"
817 "Add this NAME to the list\n")
818{
819 return add_apn_ggsn_mapping(vty, argv[0], "", 0);
820}
821
822DEFUN(cfg_no_apn_name, cfg_no_apn_name_cmd,
823 "no access-point-name NAME",
824 NO_STR "Configure a global list of allowed APNs\n"
825 "Remove entry with NAME\n")
826{
827 struct apn_ctx *apn_ctx = sgsn_apn_ctx_by_name(argv[0], "");
828 if (!apn_ctx)
829 return CMD_SUCCESS;
830
831 sgsn_apn_ctx_free(apn_ctx);
832 return CMD_SUCCESS;
833}
834
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +0200835DEFUN(cfg_cdr_filename, cfg_cdr_filename_cmd,
836 "cdr filename NAME",
837 "CDR\nSet filename\nname\n")
838{
839 talloc_free(g_cfg->cdr.filename);
840 g_cfg->cdr.filename = talloc_strdup(tall_vty_ctx, argv[0]);
841 return CMD_SUCCESS;
842}
843
844DEFUN(cfg_no_cdr_filename, cfg_no_cdr_filename_cmd,
845 "no cdr filename",
846 NO_STR "CDR\nDisable CDR generation\n")
847{
848 talloc_free(g_cfg->cdr.filename);
849 g_cfg->cdr.filename = NULL;
850 return CMD_SUCCESS;
851}
852
853DEFUN(cfg_cdr_interval, cfg_cdr_interval_cmd,
854 "cdr interval <1-2147483647>",
855 "CDR\nPDP periodic log interval\nSeconds\n")
856{
857 g_cfg->cdr.interval = atoi(argv[0]);
858 return CMD_SUCCESS;
859}
860
Harald Welte288be162010-05-01 16:48:27 +0200861int sgsn_vty_init(void)
862{
Harald Welted193cb32010-05-17 22:58:03 +0200863 install_element_ve(&show_sgsn_cmd);
864 //install_element_ve(&show_mmctx_tlli_cmd);
865 install_element_ve(&show_mmctx_imsi_cmd);
866 install_element_ve(&show_mmctx_all_cmd);
867 install_element_ve(&show_pdpctx_all_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100868 install_element_ve(&show_subscr_cache_cmd);
869
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100870 install_element(ENABLE_NODE, &update_subscr_insert_auth_triplet_cmd);
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100871 install_element(ENABLE_NODE, &update_subscr_create_cmd);
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100872 install_element(ENABLE_NODE, &update_subscr_destroy_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100873 install_element(ENABLE_NODE, &update_subscr_cancel_cmd);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100874 install_element(ENABLE_NODE, &update_subscr_update_location_result_cmd);
875 install_element(ENABLE_NODE, &update_subscr_update_auth_info_cmd);
Harald Welte288be162010-05-01 16:48:27 +0200876
877 install_element(CONFIG_NODE, &cfg_sgsn_cmd);
878 install_node(&sgsn_node, config_write_sgsn);
Jacob Erlbeck36722e12013-10-29 09:30:30 +0100879 vty_install_default(SGSN_NODE);
Harald Weltee300d002010-06-02 12:41:34 +0200880 install_element(SGSN_NODE, &cfg_sgsn_bind_addr_cmd);
Harald Welted193cb32010-05-17 22:58:03 +0200881 install_element(SGSN_NODE, &cfg_ggsn_remote_ip_cmd);
882 //install_element(SGSN_NODE, &cfg_ggsn_remote_port_cmd);
883 install_element(SGSN_NODE, &cfg_ggsn_gtp_version_cmd);
Harald Welte7f6da482013-03-19 11:00:13 +0100884 install_element(SGSN_NODE, &cfg_imsi_acl_cmd);
Harald Welte3dfb5492013-03-19 11:48:54 +0100885 install_element(SGSN_NODE, &cfg_auth_policy_cmd);
Jacob Erlbeck39f040d2014-12-18 12:46:47 +0100886 install_element(SGSN_NODE, &cfg_gsup_remote_ip_cmd);
887 install_element(SGSN_NODE, &cfg_gsup_remote_port_cmd);
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100888 install_element(SGSN_NODE, &cfg_apn_ggsn_cmd);
889 install_element(SGSN_NODE, &cfg_apn_imsi_ggsn_cmd);
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +0100890 install_element(SGSN_NODE, &cfg_apn_name_cmd);
891 install_element(SGSN_NODE, &cfg_no_apn_name_cmd);
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +0200892 install_element(SGSN_NODE, &cfg_cdr_filename_cmd);
893 install_element(SGSN_NODE, &cfg_no_cdr_filename_cmd);
894 install_element(SGSN_NODE, &cfg_cdr_interval_cmd);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800895 install_element(SGSN_NODE, &cfg_ggsn_dynamic_lookup_cmd);
Harald Welte288be162010-05-01 16:48:27 +0200896
897 return 0;
898}
899
900int sgsn_parse_config(const char *config_file, struct sgsn_config *cfg)
901{
902 int rc;
903
904 g_cfg = cfg;
Harald Welte7f6da482013-03-19 11:00:13 +0100905
Harald Weltedcccb182010-05-16 20:52:23 +0200906 rc = vty_read_config_file(config_file, NULL);
Harald Welte288be162010-05-01 16:48:27 +0200907 if (rc < 0) {
908 fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
909 return rc;
910 }
911
912 return 0;
913}