blob: b7023adb2fb6bf87b9a14781429b9af116780ac0 [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) {
Harald Welteff3bde82010-05-19 15:09:09 +0200138 vty_out(vty, " ggsn %u remote-ip %s%s", gctx->id,
Harald Welted193cb32010-05-17 22:58:03 +0200139 inet_ntoa(gctx->remote_addr), VTY_NEWLINE);
Harald Welteff3bde82010-05-19 15:09:09 +0200140 vty_out(vty, " ggsn %u gtp-version %u%s", gctx->id,
Harald Welted193cb32010-05-17 22:58:03 +0200141 gctx->gtp_version, VTY_NEWLINE);
Harald Welte288be162010-05-01 16:48:27 +0200142 }
143
Harald Welte3dfb5492013-03-19 11:48:54 +0100144 vty_out(vty, " auth-policy %s%s",
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100145 get_value_string(sgsn_auth_pol_strs, g_cfg->auth_policy),
146 VTY_NEWLINE);
Jacob Erlbeck39f040d2014-12-18 12:46:47 +0100147 if (g_cfg->gsup_server_addr.sin_addr.s_addr)
148 vty_out(vty, " gsup remote-ip %s%s",
149 inet_ntoa(g_cfg->gsup_server_addr.sin_addr), VTY_NEWLINE);
150 if (g_cfg->gsup_server_port)
151 vty_out(vty, " gsup remote-port %d%s",
152 g_cfg->gsup_server_port, VTY_NEWLINE);
Harald Welte7f6da482013-03-19 11:00:13 +0100153 llist_for_each_entry(acl, &g_cfg->imsi_acl, list)
154 vty_out(vty, " imsi-acl add %s%s", acl->imsi, VTY_NEWLINE);
155
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100156 if (llist_empty(&sgsn_apn_ctxts))
157 vty_out(vty, " ! apn * ggsn 0%s", VTY_NEWLINE);
158 llist_for_each_entry(actx, &sgsn_apn_ctxts, list) {
159 if (strlen(actx->imsi_prefix) > 0)
160 vty_out(vty, " apn %s imsi-prefix %s ggsn %d%s",
161 actx->name, actx->imsi_prefix, actx->ggsn->id,
162 VTY_NEWLINE);
163 else
164 vty_out(vty, " apn %s ggsn %d%s", actx->name,
165 actx->ggsn->id, VTY_NEWLINE);
166 }
167
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +0200168 if (g_cfg->cdr.filename)
169 vty_out(vty, " cdr filename %s%s", g_cfg->cdr.filename, VTY_NEWLINE);
170 else
171 vty_out(vty, " no cdr filename%s", VTY_NEWLINE);
172 vty_out(vty, " cdr interval %d%s", g_cfg->cdr.interval, VTY_NEWLINE);
173
Harald Welte288be162010-05-01 16:48:27 +0200174 return CMD_SUCCESS;
175}
176
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100177#define SGSN_STR "Configure the SGSN\n"
178#define GGSN_STR "Configure the GGSN information\n"
Harald Weltee300d002010-06-02 12:41:34 +0200179
180DEFUN(cfg_sgsn, cfg_sgsn_cmd,
181 "sgsn",
182 SGSN_STR)
Harald Welte288be162010-05-01 16:48:27 +0200183{
184 vty->node = SGSN_NODE;
185 return CMD_SUCCESS;
186}
187
Harald Weltee300d002010-06-02 12:41:34 +0200188DEFUN(cfg_sgsn_bind_addr, cfg_sgsn_bind_addr_cmd,
189 "gtp local-ip A.B.C.D",
190 "GTP Parameters\n"
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100191 "Set the IP address for the local GTP bind\n"
192 "IPv4 Address\n")
Harald Weltee300d002010-06-02 12:41:34 +0200193{
194 inet_aton(argv[0], &g_cfg->gtp_listenaddr.sin_addr);
195
196 return CMD_SUCCESS;
197}
198
Harald Welted193cb32010-05-17 22:58:03 +0200199DEFUN(cfg_ggsn_remote_ip, cfg_ggsn_remote_ip_cmd,
200 "ggsn <0-255> remote-ip A.B.C.D",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100201 GGSN_STR "GGSN Number\n" IP_STR "IPv4 Address\n")
Harald Welted193cb32010-05-17 22:58:03 +0200202{
203 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200204 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welte288be162010-05-01 16:48:27 +0200205
Harald Welted193cb32010-05-17 22:58:03 +0200206 inet_aton(argv[1], &ggc->remote_addr);
Harald Welte288be162010-05-01 16:48:27 +0200207
Harald Welted193cb32010-05-17 22:58:03 +0200208 return CMD_SUCCESS;
209}
210
211#if 0
212DEFUN(cfg_ggsn_remote_port, cfg_ggsn_remote_port_cmd,
213 "ggsn <0-255> remote-port <0-65535>",
214 "")
215{
216 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200217 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welted193cb32010-05-17 22:58:03 +0200218 uint16_t port = atoi(argv[1]);
219
220}
221#endif
222
223DEFUN(cfg_ggsn_gtp_version, cfg_ggsn_gtp_version_cmd,
224 "ggsn <0-255> gtp-version (0|1)",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100225 GGSN_STR "GGSN Number\n" "GTP Version\n"
226 "Version 0\n" "Version 1\n")
Harald Welted193cb32010-05-17 22:58:03 +0200227{
228 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200229 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welted193cb32010-05-17 22:58:03 +0200230
231 if (atoi(argv[1]))
232 ggc->gtp_version = 1;
233 else
234 ggc->gtp_version = 0;
235
236 return CMD_SUCCESS;
237}
238
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100239#define APN_STR "Configure the information per APN\n"
240#define APN_GW_STR "The APN gateway name optionally prefixed by '*' (wildcard)\n"
241
242static int add_apn_ggsn_mapping(struct vty *vty, const char *apn_str,
243 const char *imsi_prefix, int ggsn_id)
244{
245 struct apn_ctx *actx;
246 struct sgsn_ggsn_ctx *ggsn;
247
248 ggsn = sgsn_ggsn_ctx_by_id(ggsn_id);
249 if (ggsn == NULL) {
250 vty_out(vty, "%% a GGSN with id %d has not been defined%s",
251 ggsn_id, VTY_NEWLINE);
252 return CMD_WARNING;
253 }
254
255 actx = sgsn_apn_ctx_find_alloc(apn_str, imsi_prefix);
256 if (!actx) {
257 vty_out(vty, "%% unable to create APN context for %s/%s%s",
258 apn_str, imsi_prefix, VTY_NEWLINE);
259 return CMD_WARNING;
260 }
261
262 actx->ggsn = ggsn;
263
264 return CMD_SUCCESS;
265}
266
Harald Welted193cb32010-05-17 22:58:03 +0200267DEFUN(cfg_apn_ggsn, cfg_apn_ggsn_cmd,
268 "apn APNAME ggsn <0-255>",
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100269 APN_STR APN_GW_STR
270 "Select the GGSN to use when the APN gateway prefix matches\n"
271 "The GGSN id")
Harald Welted193cb32010-05-17 22:58:03 +0200272{
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100273
274 return add_apn_ggsn_mapping(vty, argv[0], "", atoi(argv[1]));
Harald Welted193cb32010-05-17 22:58:03 +0200275}
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100276
277DEFUN(cfg_apn_imsi_ggsn, cfg_apn_imsi_ggsn_cmd,
278 "apn APNAME imsi-prefix IMSIPRE ggsn <0-255>",
279 APN_STR APN_GW_STR
280 "Restrict rule to a certain IMSI prefix\n"
281 "An IMSI prefix\n"
282 "Select the GGSN to use when APN gateway and IMSI prefix match\n"
283 "The GGSN id")
284{
285
286 return add_apn_ggsn_mapping(vty, argv[0], argv[1], atoi(argv[2]));
287}
Harald Welted193cb32010-05-17 22:58:03 +0200288
289const struct value_string gprs_mm_st_strs[] = {
290 { GMM_DEREGISTERED, "DEREGISTERED" },
291 { GMM_COMMON_PROC_INIT, "COMMON PROCEDURE (INIT)" },
292 { GMM_REGISTERED_NORMAL, "REGISTERED (NORMAL)" },
Harald Weltebffeff82010-06-09 15:50:45 +0200293 { GMM_REGISTERED_SUSPENDED, "REGISTERED (SUSPENDED)" },
Harald Welted193cb32010-05-17 22:58:03 +0200294 { GMM_DEREGISTERED_INIT, "DEREGISTERED (INIT)" },
295 { 0, NULL }
296};
297
298static void vty_dump_pdp(struct vty *vty, const char *pfx,
299 struct sgsn_pdp_ctx *pdp)
300{
Jacob Erlbeck99985b52014-10-13 10:32:00 +0200301 const char *imsi = pdp->mm ? pdp->mm->imsi : "(detaching)";
Harald Welted193cb32010-05-17 22:58:03 +0200302 vty_out(vty, "%sPDP Context IMSI: %s, SAPI: %u, NSAPI: %u%s",
Jacob Erlbeck99985b52014-10-13 10:32:00 +0200303 pfx, imsi, pdp->sapi, pdp->nsapi, VTY_NEWLINE);
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200304 vty_out(vty, "%s APN: %s%s", pfx,
305 gprs_apn2str(pdp->lib->apn_use.v, pdp->lib->apn_use.l),
306 VTY_NEWLINE);
307 vty_out(vty, "%s PDP Address: %s%s", pfx,
308 gprs_pdpaddr2str(pdp->lib->eua.v, pdp->lib->eua.l),
309 VTY_NEWLINE);
Harald Welteefbdee92010-06-10 00:20:12 +0200310 vty_out_rate_ctr_group(vty, " ", pdp->ctrg);
Harald Welted193cb32010-05-17 22:58:03 +0200311}
312
313static void vty_dump_mmctx(struct vty *vty, const char *pfx,
314 struct sgsn_mm_ctx *mm, int pdp)
315{
316 vty_out(vty, "%sMM Context for IMSI %s, IMEI %s, P-TMSI %08x%s",
317 pfx, mm->imsi, mm->imei, mm->p_tmsi, VTY_NEWLINE);
Holger Hans Peter Freyther8ee13e22015-05-18 10:00:03 +0200318 vty_out(vty, "%s MSISDN: %s, TLLI: %08x%s HLR: %s",
319 pfx, mm->msisdn, mm->tlli, mm->hlr, VTY_NEWLINE);
Harald Welted193cb32010-05-17 22:58:03 +0200320 vty_out(vty, "%s MM State: %s, Routeing Area: %u-%u-%u-%u, "
321 "Cell ID: %u%s", pfx,
322 get_value_string(gprs_mm_st_strs, mm->mm_state),
323 mm->ra.mcc, mm->ra.mnc, mm->ra.lac, mm->ra.rac,
324 mm->cell_id, VTY_NEWLINE);
325
Harald Welte8acd88f2010-05-18 10:57:45 +0200326 vty_out_rate_ctr_group(vty, " ", mm->ctrg);
327
Harald Welted193cb32010-05-17 22:58:03 +0200328 if (pdp) {
329 struct sgsn_pdp_ctx *pdp;
330
331 llist_for_each_entry(pdp, &mm->pdp_list, list)
332 vty_dump_pdp(vty, " ", pdp);
333 }
334}
335
336DEFUN(show_sgsn, show_sgsn_cmd, "show sgsn",
337 SHOW_STR "Display information about the SGSN")
338{
Jacob Erlbeck80547992014-12-19 19:19:46 +0100339 if (sgsn->gsup_client) {
340 struct ipa_client_conn *link = sgsn->gsup_client->link;
341 vty_out(vty,
342 " Remote authorization: %sconnected to %s:%d via GSUP%s",
343 sgsn->gsup_client->is_connected ? "" : "not ",
344 link->addr, link->port,
345 VTY_NEWLINE);
346 }
Harald Welted193cb32010-05-17 22:58:03 +0200347 /* FIXME: statistics */
348 return CMD_SUCCESS;
349}
350
351#define MMCTX_STR "MM Context\n"
352#define INCLUDE_PDP_STR "Include PDP Context Information\n"
353
354#if 0
355DEFUN(show_mmctx_tlli, show_mmctx_tlli_cmd,
356 "show mm-context tlli HEX [pdp]",
357 SHOW_STR MMCTX_STR "Identify by TLLI\n" "TLLI\n" INCLUDE_PDP_STR)
358{
359 uint32_t tlli;
360 struct sgsn_mm_ctx *mm;
361
362 tlli = strtoul(argv[0], NULL, 16);
363 mm = sgsn_mm_ctx_by_tlli(tlli);
364 if (!mm) {
365 vty_out(vty, "No MM context for TLLI %08x%s",
366 tlli, VTY_NEWLINE);
367 return CMD_WARNING;
368 }
369 vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
370 return CMD_SUCCESS;
371}
372#endif
373
374DEFUN(swow_mmctx_imsi, show_mmctx_imsi_cmd,
375 "show mm-context imsi IMSI [pdp]",
376 SHOW_STR MMCTX_STR "Identify by IMSI\n" "IMSI of the MM Context\n"
377 INCLUDE_PDP_STR)
378{
379 struct sgsn_mm_ctx *mm;
380
381 mm = sgsn_mm_ctx_by_imsi(argv[0]);
382 if (!mm) {
383 vty_out(vty, "No MM context for IMSI %s%s",
384 argv[0], VTY_NEWLINE);
385 return CMD_WARNING;
386 }
387 vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
388 return CMD_SUCCESS;
389}
390
391DEFUN(swow_mmctx_all, show_mmctx_all_cmd,
392 "show mm-context all [pdp]",
393 SHOW_STR MMCTX_STR "All MM Contexts\n" INCLUDE_PDP_STR)
394{
395 struct sgsn_mm_ctx *mm;
396
397 llist_for_each_entry(mm, &sgsn_mm_ctxts, list)
398 vty_dump_mmctx(vty, "", mm, argv[0] ? 1 : 0);
399
400 return CMD_SUCCESS;
401}
402
Harald Welted193cb32010-05-17 22:58:03 +0200403DEFUN(show_pdpctx_all, show_pdpctx_all_cmd,
404 "show pdp-context all",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100405 SHOW_STR "Display information on PDP Context\n" "Show everything\n")
Harald Welted193cb32010-05-17 22:58:03 +0200406{
407 struct sgsn_pdp_ctx *pdp;
408
409 llist_for_each_entry(pdp, &sgsn_pdp_ctxts, g_list)
410 vty_dump_pdp(vty, "", pdp);
411
412 return CMD_SUCCESS;
413}
Harald Welte288be162010-05-01 16:48:27 +0200414
Harald Welte7f6da482013-03-19 11:00:13 +0100415
416DEFUN(imsi_acl, cfg_imsi_acl_cmd,
417 "imsi-acl (add|del) IMSI",
418 "Access Control List of foreign IMSIs\n"
419 "Add IMSI to ACL\n"
420 "Remove IMSI from ACL\n"
421 "IMSI of subscriber\n")
422{
423 const char *op = argv[0];
424 const char *imsi = argv[1];
425 int rc;
426
427 if (!strcmp(op, "add"))
Jacob Erlbeck3b5d4072014-10-24 15:11:03 +0200428 rc = sgsn_acl_add(imsi, g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +0100429 else
Jacob Erlbeck3b5d4072014-10-24 15:11:03 +0200430 rc = sgsn_acl_del(imsi, g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +0100431
432 if (rc < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100433 vty_out(vty, "%% unable to %s ACL%s", op, VTY_NEWLINE);
434
Harald Welte7f6da482013-03-19 11:00:13 +0100435 return CMD_WARNING;
436 }
437
438 return CMD_SUCCESS;
439}
440
Harald Welte3dfb5492013-03-19 11:48:54 +0100441DEFUN(cfg_auth_policy, cfg_auth_policy_cmd,
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100442 "auth-policy (accept-all|closed|acl-only|remote)",
Harald Welte3dfb5492013-03-19 11:48:54 +0100443 "Autorization Policy of SGSN\n"
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100444 "Accept all IMSIs (DANGEROUS)\n"
445 "Accept only home network subscribers or those in the ACL\n"
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100446 "Accept only subscribers in the ACL\n"
447 "Use remote subscription data only (HLR)\n")
Harald Welte3dfb5492013-03-19 11:48:54 +0100448{
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100449 int val = get_string_value(sgsn_auth_pol_strs, argv[0]);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100450 OSMO_ASSERT(val >= SGSN_AUTH_POLICY_OPEN && val <= SGSN_AUTH_POLICY_REMOTE);
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100451 g_cfg->auth_policy = val;
Jacob Erlbeck9d4f46c2014-12-17 13:20:08 +0100452 g_cfg->require_authentication = (val == SGSN_AUTH_POLICY_REMOTE);
Jacob Erlbeck771573c2014-12-19 18:08:48 +0100453 g_cfg->require_update_location = (val == SGSN_AUTH_POLICY_REMOTE);
Harald Welte3dfb5492013-03-19 11:48:54 +0100454
455 return CMD_SUCCESS;
456}
457
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100458/* Subscriber */
459#include <openbsc/gsm_subscriber.h>
460
461static void subscr_dump_full_vty(struct vty *vty, struct gsm_subscriber *subscr, int pending)
462{
463 char expire_time[200];
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100464 struct gsm_auth_tuple *at;
465 int at_idx;
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100466 struct sgsn_subscriber_pdp_data *pdp;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100467
468 vty_out(vty, " ID: %llu, Authorized: %d%s", subscr->id,
469 subscr->authorized, VTY_NEWLINE);
470 if (strlen(subscr->name))
471 vty_out(vty, " Name: '%s'%s", subscr->name, VTY_NEWLINE);
472 if (strlen(subscr->extension))
473 vty_out(vty, " Extension: %s%s", subscr->extension,
474 VTY_NEWLINE);
475 vty_out(vty, " LAC: %d/0x%x%s",
476 subscr->lac, subscr->lac, VTY_NEWLINE);
477 vty_out(vty, " IMSI: %s%s", subscr->imsi, VTY_NEWLINE);
478 if (subscr->tmsi != GSM_RESERVED_TMSI)
479 vty_out(vty, " TMSI: %08X%s", subscr->tmsi,
480 VTY_NEWLINE);
Holger Hans Peter Freytherf7b38262015-04-23 16:58:33 -0400481 if (subscr->sgsn_data->msisdn_len > 0)
482 vty_out(vty, " MSISDN (BCD): %s%s",
483 osmo_hexdump(subscr->sgsn_data->msisdn,
484 subscr->sgsn_data->msisdn_len),
485 VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100486
487 if (strlen(subscr->equipment.imei) > 0)
488 vty_out(vty, " IMEI: %s%s", subscr->equipment.imei, VTY_NEWLINE);
489
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100490 for (at_idx = 0; at_idx < ARRAY_SIZE(subscr->sgsn_data->auth_triplets);
491 at_idx++) {
492 at = &subscr->sgsn_data->auth_triplets[at_idx];
493 if (at->key_seq == GSM_KEY_SEQ_INVAL)
494 continue;
495
496 vty_out(vty, " A3A8 tuple (used %d times): ",
497 at->use_count);
498 vty_out(vty, " seq # : %d, ",
499 at->key_seq);
500 vty_out(vty, " RAND : %s, ",
501 osmo_hexdump(at->rand, sizeof(at->rand)));
502 vty_out(vty, " SRES : %s, ",
503 osmo_hexdump(at->sres, sizeof(at->sres)));
504 vty_out(vty, " Kc : %s%s",
505 osmo_hexdump(at->kc, sizeof(at->kc)),
506 VTY_NEWLINE);
507 }
508
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100509 llist_for_each_entry(pdp, &subscr->sgsn_data->pdp_list, list) {
Holger Hans Peter Freytherd05e0692015-04-23 16:59:04 -0400510 vty_out(vty, " PDP info: Id: %d, Type: 0x%04x, APN: '%s' QoS: %s%s",
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100511 pdp->context_id, pdp->pdp_type, pdp->apn_str,
Holger Hans Peter Freytherd05e0692015-04-23 16:59:04 -0400512 osmo_hexdump(pdp->qos_subscribed, pdp->qos_subscribed_len),
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100513 VTY_NEWLINE);
514 }
515
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100516 /* print the expiration time of a subscriber */
517 if (subscr->expire_lu) {
518 strftime(expire_time, sizeof(expire_time),
519 "%a, %d %b %Y %T %z", localtime(&subscr->expire_lu));
520 expire_time[sizeof(expire_time) - 1] = '\0';
521 vty_out(vty, " Expiration Time: %s%s", expire_time, VTY_NEWLINE);
522 }
523
524 if (subscr->flags)
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100525 vty_out(vty, " Flags: %s%s%s%s%s%s",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100526 subscr->flags & GSM_SUBSCRIBER_FIRST_CONTACT ?
527 "FIRST_CONTACT " : "",
528 subscr->flags & GPRS_SUBSCRIBER_CANCELLED ?
529 "CANCELLED " : "",
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100530 subscr->flags & GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING ?
531 "UPDATE_LOCATION_PENDING " : "",
532 subscr->flags & GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING ?
533 "AUTH_INFO_PENDING " : "",
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100534 subscr->flags & GPRS_SUBSCRIBER_ENABLE_PURGE ?
535 "ENABLE_PURGE " : "",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100536 VTY_NEWLINE);
537
538 vty_out(vty, " Use count: %u%s", subscr->use_count, VTY_NEWLINE);
539}
540
541DEFUN(show_subscr_cache,
542 show_subscr_cache_cmd,
543 "show subscriber cache",
544 SHOW_STR "Show information about subscribers\n"
545 "Display contents of subscriber cache\n")
546{
547 struct gsm_subscriber *subscr;
548
549 llist_for_each_entry(subscr, &active_subscribers, entry) {
550 vty_out(vty, " Subscriber:%s", VTY_NEWLINE);
551 subscr_dump_full_vty(vty, subscr, 0);
552 }
553
554 return CMD_SUCCESS;
555}
556
557#define UPDATE_SUBSCR_STR "update-subscriber imsi IMSI "
558#define UPDATE_SUBSCR_HELP "Update subscriber list\n" \
559 "Use the IMSI to select the subscriber\n" \
560 "The IMSI\n"
561
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100562#define UPDATE_SUBSCR_INSERT_HELP "Insert data into the subscriber record\n"
563
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100564DEFUN(update_subscr_insert_auth_triplet, update_subscr_insert_auth_triplet_cmd,
565 UPDATE_SUBSCR_STR "insert auth-triplet <1-5> sres SRES rand RAND kc KC",
566 UPDATE_SUBSCR_HELP
567 UPDATE_SUBSCR_INSERT_HELP
568 "Update authentication triplet\n"
569 "Triplet index\n"
570 "Set SRES value\nSRES value (4 byte) in hex\n"
571 "Set RAND value\nRAND value (16 byte) in hex\n"
572 "Set Kc value\nKc value (8 byte) in hex\n")
573{
574 const char *imsi = argv[0];
575 const int cksn = atoi(argv[1]) - 1;
576 const char *sres_str = argv[2];
577 const char *rand_str = argv[3];
578 const char *kc_str = argv[4];
579 struct gsm_auth_tuple at = {0,};
580
581 struct gsm_subscriber *subscr;
582
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100583 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100584 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100585 vty_out(vty, "%% unable get subscriber record for %s%s",
586 imsi, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100587 return CMD_WARNING;
588 }
589
590 OSMO_ASSERT(subscr->sgsn_data);
591
Jacob Erlbeck17fb3d42015-01-05 09:43:51 +0100592 if (osmo_hexparse(sres_str, &at.sres[0], sizeof(at.sres)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100593 vty_out(vty, "%% invalid SRES value '%s'%s",
594 sres_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100595 goto failed;
596 }
Jacob Erlbeck17fb3d42015-01-05 09:43:51 +0100597 if (osmo_hexparse(rand_str, &at.rand[0], sizeof(at.rand)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100598 vty_out(vty, "%% invalid RAND value '%s'%s",
599 rand_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100600 goto failed;
601 }
Jacob Erlbeck17fb3d42015-01-05 09:43:51 +0100602 if (osmo_hexparse(kc_str, &at.kc[0], sizeof(at.kc)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100603 vty_out(vty, "%% invalid Kc value '%s'%s",
604 kc_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100605 goto failed;
606 }
607 at.key_seq = cksn;
608
609 subscr->sgsn_data->auth_triplets[cksn] = at;
610 subscr->sgsn_data->auth_triplets_updated = 1;
611
612 subscr_put(subscr);
613
614 return CMD_SUCCESS;
615
616failed:
617 subscr_put(subscr);
618 return CMD_SUCCESS;
619}
620
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100621DEFUN(update_subscr_cancel, update_subscr_cancel_cmd,
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100622 UPDATE_SUBSCR_STR "cancel (update-procedure|subscription-withdraw)",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100623 UPDATE_SUBSCR_HELP
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100624 "Cancel (remove) subscriber record\n"
625 "The MS moved to another SGSN\n"
626 "The subscription is no longer valid\n")
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100627{
628 const char *imsi = argv[0];
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100629 const char *cancel_type = argv[1];
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100630
631 struct gsm_subscriber *subscr;
632
633 subscr = gprs_subscr_get_by_imsi(imsi);
634 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100635 vty_out(vty, "%% no subscriber record for %s%s",
636 imsi, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100637 return CMD_WARNING;
638 }
639
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100640 if (strcmp(cancel_type, "update-procedure") == 0)
641 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
642 else
643 subscr->sgsn_data->error_cause = GMM_CAUSE_IMPL_DETACHED;
644
Jacob Erlbeck37139e52015-01-23 13:52:55 +0100645 gprs_subscr_cancel(subscr);
646 subscr_put(subscr);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100647
648 return CMD_SUCCESS;
649}
650
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100651DEFUN(update_subscr_create, update_subscr_create_cmd,
652 UPDATE_SUBSCR_STR "create",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100653 UPDATE_SUBSCR_HELP
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100654 "Create a subscriber entry\n")
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100655{
656 const char *imsi = argv[0];
657
658 struct gsm_subscriber *subscr;
659
660 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100661 if (subscr) {
662 vty_out(vty, "%% subscriber record already exists for %s%s",
663 imsi, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100664 return CMD_WARNING;
665 }
666
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100667 subscr = gprs_subscr_get_or_create(imsi);
668 subscr->keep_in_ram = 1;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100669 subscr_put(subscr);
670
671 return CMD_SUCCESS;
672}
673
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100674DEFUN(update_subscr_destroy, update_subscr_destroy_cmd,
675 UPDATE_SUBSCR_STR "destroy",
676 UPDATE_SUBSCR_HELP
677 "Destroy a subscriber entry\n")
678{
679 const char *imsi = argv[0];
680
681 struct gsm_subscriber *subscr;
682
683 subscr = gprs_subscr_get_by_imsi(imsi);
684 if (!subscr) {
685 vty_out(vty, "%% subscriber record does not exist for %s%s",
686 imsi, VTY_NEWLINE);
687 return CMD_WARNING;
688 }
689
690 subscr->keep_in_ram = 0;
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100691 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100692 gprs_subscr_cancel(subscr);
693 if (subscr->use_count > 1)
694 vty_out(vty, "%% subscriber is still in use%s",
695 VTY_NEWLINE);
696 subscr_put(subscr);
697
698 return CMD_SUCCESS;
699}
700
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100701#define UL_ERR_STR "system-failure|data-missing|unexpected-data-value|" \
702 "unknown-subscriber|roaming-not-allowed"
703
704#define UL_ERR_HELP \
705 "Force error code SystemFailure\n" \
706 "Force error code DataMissing\n" \
707 "Force error code UnexpectedDataValue\n" \
708 "Force error code UnknownSubscriber\n" \
709 "Force error code RoamingNotAllowed\n"
710
711DEFUN(update_subscr_update_location_result, update_subscr_update_location_result_cmd,
712 UPDATE_SUBSCR_STR "update-location-result (ok|" UL_ERR_STR ")",
713 UPDATE_SUBSCR_HELP
714 "Complete the update location procedure\n"
715 "The update location request succeeded\n"
716 UL_ERR_HELP)
717{
718 const char *imsi = argv[0];
719 const char *ret_code_str = argv[1];
720
721 struct gsm_subscriber *subscr;
722
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100723 const struct value_string cause_mapping[] = {
724 { GMM_CAUSE_NET_FAIL, "system-failure" },
725 { GMM_CAUSE_INV_MAND_INFO, "data-missing" },
726 { GMM_CAUSE_PROTO_ERR_UNSPEC, "unexpected-data-value" },
727 { GMM_CAUSE_IMSI_UNKNOWN, "unknown-subscriber" },
728 { GMM_CAUSE_GPRS_NOTALLOWED, "roaming-not-allowed" },
729 { 0, NULL }
730 };
731
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100732 subscr = gprs_subscr_get_by_imsi(imsi);
733 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100734 vty_out(vty, "%% unable to get subscriber record for %s%s",
735 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100736 return CMD_WARNING;
737 }
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100738
739 if (strcmp(ret_code_str, "ok") == 0) {
740 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100741 subscr->authorized = 1;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100742 } else {
743 subscr->sgsn_data->error_cause =
744 get_string_value(cause_mapping, ret_code_str);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100745 subscr->authorized = 0;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100746 }
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100747
748 gprs_subscr_update(subscr);
749
750 subscr_put(subscr);
751
752 return CMD_SUCCESS;
753}
754
755DEFUN(update_subscr_update_auth_info, update_subscr_update_auth_info_cmd,
756 UPDATE_SUBSCR_STR "update-auth-info",
757 UPDATE_SUBSCR_HELP
758 "Complete the send authentication info procedure\n")
759{
760 const char *imsi = argv[0];
761
762 struct gsm_subscriber *subscr;
763
764 subscr = gprs_subscr_get_by_imsi(imsi);
765 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100766 vty_out(vty, "%% unable to get subscriber record for %s%s",
767 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100768 return CMD_WARNING;
769 }
770
771 gprs_subscr_update_auth_info(subscr);
772
773 subscr_put(subscr);
774
775 return CMD_SUCCESS;
776}
777
Jacob Erlbeck39f040d2014-12-18 12:46:47 +0100778DEFUN(cfg_gsup_remote_ip, cfg_gsup_remote_ip_cmd,
779 "gsup remote-ip A.B.C.D",
780 "GSUP Parameters\n"
781 "Set the IP address of the remote GSUP server\n"
782 "IPv4 Address\n")
783{
784 inet_aton(argv[0], &g_cfg->gsup_server_addr.sin_addr);
785
786 return CMD_SUCCESS;
787}
788
789DEFUN(cfg_gsup_remote_port, cfg_gsup_remote_port_cmd,
790 "gsup remote-port <0-65535>",
791 "GSUP Parameters\n"
792 "Set the TCP port of the remote GSUP server\n"
793 "Remote TCP port\n")
794{
795 g_cfg->gsup_server_port = atoi(argv[0]);
796
797 return CMD_SUCCESS;
798}
799
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +0100800DEFUN(cfg_apn_name, cfg_apn_name_cmd,
801 "access-point-name NAME",
802 "Configure a global list of allowed APNs\n"
803 "Add this NAME to the list\n")
804{
805 return add_apn_ggsn_mapping(vty, argv[0], "", 0);
806}
807
808DEFUN(cfg_no_apn_name, cfg_no_apn_name_cmd,
809 "no access-point-name NAME",
810 NO_STR "Configure a global list of allowed APNs\n"
811 "Remove entry with NAME\n")
812{
813 struct apn_ctx *apn_ctx = sgsn_apn_ctx_by_name(argv[0], "");
814 if (!apn_ctx)
815 return CMD_SUCCESS;
816
817 sgsn_apn_ctx_free(apn_ctx);
818 return CMD_SUCCESS;
819}
820
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +0200821DEFUN(cfg_cdr_filename, cfg_cdr_filename_cmd,
822 "cdr filename NAME",
823 "CDR\nSet filename\nname\n")
824{
825 talloc_free(g_cfg->cdr.filename);
826 g_cfg->cdr.filename = talloc_strdup(tall_vty_ctx, argv[0]);
827 return CMD_SUCCESS;
828}
829
830DEFUN(cfg_no_cdr_filename, cfg_no_cdr_filename_cmd,
831 "no cdr filename",
832 NO_STR "CDR\nDisable CDR generation\n")
833{
834 talloc_free(g_cfg->cdr.filename);
835 g_cfg->cdr.filename = NULL;
836 return CMD_SUCCESS;
837}
838
839DEFUN(cfg_cdr_interval, cfg_cdr_interval_cmd,
840 "cdr interval <1-2147483647>",
841 "CDR\nPDP periodic log interval\nSeconds\n")
842{
843 g_cfg->cdr.interval = atoi(argv[0]);
844 return CMD_SUCCESS;
845}
846
Harald Welte288be162010-05-01 16:48:27 +0200847int sgsn_vty_init(void)
848{
Harald Welted193cb32010-05-17 22:58:03 +0200849 install_element_ve(&show_sgsn_cmd);
850 //install_element_ve(&show_mmctx_tlli_cmd);
851 install_element_ve(&show_mmctx_imsi_cmd);
852 install_element_ve(&show_mmctx_all_cmd);
853 install_element_ve(&show_pdpctx_all_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100854 install_element_ve(&show_subscr_cache_cmd);
855
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100856 install_element(ENABLE_NODE, &update_subscr_insert_auth_triplet_cmd);
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100857 install_element(ENABLE_NODE, &update_subscr_create_cmd);
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100858 install_element(ENABLE_NODE, &update_subscr_destroy_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100859 install_element(ENABLE_NODE, &update_subscr_cancel_cmd);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100860 install_element(ENABLE_NODE, &update_subscr_update_location_result_cmd);
861 install_element(ENABLE_NODE, &update_subscr_update_auth_info_cmd);
Harald Welte288be162010-05-01 16:48:27 +0200862
863 install_element(CONFIG_NODE, &cfg_sgsn_cmd);
864 install_node(&sgsn_node, config_write_sgsn);
Jacob Erlbeck36722e12013-10-29 09:30:30 +0100865 vty_install_default(SGSN_NODE);
Harald Weltee300d002010-06-02 12:41:34 +0200866 install_element(SGSN_NODE, &cfg_sgsn_bind_addr_cmd);
Harald Welted193cb32010-05-17 22:58:03 +0200867 install_element(SGSN_NODE, &cfg_ggsn_remote_ip_cmd);
868 //install_element(SGSN_NODE, &cfg_ggsn_remote_port_cmd);
869 install_element(SGSN_NODE, &cfg_ggsn_gtp_version_cmd);
Harald Welte7f6da482013-03-19 11:00:13 +0100870 install_element(SGSN_NODE, &cfg_imsi_acl_cmd);
Harald Welte3dfb5492013-03-19 11:48:54 +0100871 install_element(SGSN_NODE, &cfg_auth_policy_cmd);
Jacob Erlbeck39f040d2014-12-18 12:46:47 +0100872 install_element(SGSN_NODE, &cfg_gsup_remote_ip_cmd);
873 install_element(SGSN_NODE, &cfg_gsup_remote_port_cmd);
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100874 install_element(SGSN_NODE, &cfg_apn_ggsn_cmd);
875 install_element(SGSN_NODE, &cfg_apn_imsi_ggsn_cmd);
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +0100876 install_element(SGSN_NODE, &cfg_apn_name_cmd);
877 install_element(SGSN_NODE, &cfg_no_apn_name_cmd);
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +0200878 install_element(SGSN_NODE, &cfg_cdr_filename_cmd);
879 install_element(SGSN_NODE, &cfg_no_cdr_filename_cmd);
880 install_element(SGSN_NODE, &cfg_cdr_interval_cmd);
Harald Welte288be162010-05-01 16:48:27 +0200881
882 return 0;
883}
884
885int sgsn_parse_config(const char *config_file, struct sgsn_config *cfg)
886{
887 int rc;
888
889 g_cfg = cfg;
Harald Welte7f6da482013-03-19 11:00:13 +0100890
Harald Weltedcccb182010-05-16 20:52:23 +0200891 rc = vty_read_config_file(config_file, NULL);
Harald Welte288be162010-05-01 16:48:27 +0200892 if (rc < 0) {
893 fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
894 return rc;
895 }
896
897 return 0;
898}