blob: 70d299b4237637cb555415e872697b7ce51fc315 [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;
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800131 struct ares_addr_node *server;
Harald Welte288be162010-05-01 16:48:27 +0200132
133 vty_out(vty, "sgsn%s", VTY_NEWLINE);
134
Harald Weltee300d002010-06-02 12:41:34 +0200135 vty_out(vty, " gtp local-ip %s%s",
136 inet_ntoa(g_cfg->gtp_listenaddr.sin_addr), VTY_NEWLINE);
137
Harald Welted193cb32010-05-17 22:58:03 +0200138 llist_for_each_entry(gctx, &sgsn_ggsn_ctxts, list) {
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800139 if (gctx->id == UINT32_MAX)
140 continue;
141
Harald Welteff3bde82010-05-19 15:09:09 +0200142 vty_out(vty, " ggsn %u remote-ip %s%s", gctx->id,
Harald Welted193cb32010-05-17 22:58:03 +0200143 inet_ntoa(gctx->remote_addr), VTY_NEWLINE);
Harald Welteff3bde82010-05-19 15:09:09 +0200144 vty_out(vty, " ggsn %u gtp-version %u%s", gctx->id,
Harald Welted193cb32010-05-17 22:58:03 +0200145 gctx->gtp_version, VTY_NEWLINE);
Harald Welte288be162010-05-01 16:48:27 +0200146 }
147
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800148 if (sgsn->cfg.dynamic_lookup)
149 vty_out(vty, " ggsn dynamic%s", VTY_NEWLINE);
150
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800151 for (server = sgsn->ares_servers; server; server = server->next)
152 vty_out(vty, " grx-dns-add %s%s", inet_ntoa(server->addr.addr4), VTY_NEWLINE);
153
Harald Welte3dfb5492013-03-19 11:48:54 +0100154 vty_out(vty, " auth-policy %s%s",
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100155 get_value_string(sgsn_auth_pol_strs, g_cfg->auth_policy),
156 VTY_NEWLINE);
Jacob Erlbeck39f040d2014-12-18 12:46:47 +0100157 if (g_cfg->gsup_server_addr.sin_addr.s_addr)
158 vty_out(vty, " gsup remote-ip %s%s",
159 inet_ntoa(g_cfg->gsup_server_addr.sin_addr), VTY_NEWLINE);
160 if (g_cfg->gsup_server_port)
161 vty_out(vty, " gsup remote-port %d%s",
162 g_cfg->gsup_server_port, VTY_NEWLINE);
Harald Welte7f6da482013-03-19 11:00:13 +0100163 llist_for_each_entry(acl, &g_cfg->imsi_acl, list)
164 vty_out(vty, " imsi-acl add %s%s", acl->imsi, VTY_NEWLINE);
165
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100166 if (llist_empty(&sgsn_apn_ctxts))
167 vty_out(vty, " ! apn * ggsn 0%s", VTY_NEWLINE);
168 llist_for_each_entry(actx, &sgsn_apn_ctxts, list) {
169 if (strlen(actx->imsi_prefix) > 0)
170 vty_out(vty, " apn %s imsi-prefix %s ggsn %d%s",
171 actx->name, actx->imsi_prefix, actx->ggsn->id,
172 VTY_NEWLINE);
173 else
174 vty_out(vty, " apn %s ggsn %d%s", actx->name,
175 actx->ggsn->id, VTY_NEWLINE);
176 }
177
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +0200178 if (g_cfg->cdr.filename)
179 vty_out(vty, " cdr filename %s%s", g_cfg->cdr.filename, VTY_NEWLINE);
180 else
181 vty_out(vty, " no cdr filename%s", VTY_NEWLINE);
182 vty_out(vty, " cdr interval %d%s", g_cfg->cdr.interval, VTY_NEWLINE);
183
Harald Welte288be162010-05-01 16:48:27 +0200184 return CMD_SUCCESS;
185}
186
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100187#define SGSN_STR "Configure the SGSN\n"
188#define GGSN_STR "Configure the GGSN information\n"
Harald Weltee300d002010-06-02 12:41:34 +0200189
190DEFUN(cfg_sgsn, cfg_sgsn_cmd,
191 "sgsn",
192 SGSN_STR)
Harald Welte288be162010-05-01 16:48:27 +0200193{
194 vty->node = SGSN_NODE;
195 return CMD_SUCCESS;
196}
197
Harald Weltee300d002010-06-02 12:41:34 +0200198DEFUN(cfg_sgsn_bind_addr, cfg_sgsn_bind_addr_cmd,
199 "gtp local-ip A.B.C.D",
200 "GTP Parameters\n"
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100201 "Set the IP address for the local GTP bind\n"
202 "IPv4 Address\n")
Harald Weltee300d002010-06-02 12:41:34 +0200203{
204 inet_aton(argv[0], &g_cfg->gtp_listenaddr.sin_addr);
205
206 return CMD_SUCCESS;
207}
208
Harald Welted193cb32010-05-17 22:58:03 +0200209DEFUN(cfg_ggsn_remote_ip, cfg_ggsn_remote_ip_cmd,
210 "ggsn <0-255> remote-ip A.B.C.D",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100211 GGSN_STR "GGSN Number\n" IP_STR "IPv4 Address\n")
Harald Welted193cb32010-05-17 22:58:03 +0200212{
213 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200214 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welte288be162010-05-01 16:48:27 +0200215
Harald Welted193cb32010-05-17 22:58:03 +0200216 inet_aton(argv[1], &ggc->remote_addr);
Harald Welte288be162010-05-01 16:48:27 +0200217
Harald Welted193cb32010-05-17 22:58:03 +0200218 return CMD_SUCCESS;
219}
220
221#if 0
222DEFUN(cfg_ggsn_remote_port, cfg_ggsn_remote_port_cmd,
223 "ggsn <0-255> remote-port <0-65535>",
224 "")
225{
226 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200227 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welted193cb32010-05-17 22:58:03 +0200228 uint16_t port = atoi(argv[1]);
229
230}
231#endif
232
233DEFUN(cfg_ggsn_gtp_version, cfg_ggsn_gtp_version_cmd,
234 "ggsn <0-255> gtp-version (0|1)",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100235 GGSN_STR "GGSN Number\n" "GTP Version\n"
236 "Version 0\n" "Version 1\n")
Harald Welted193cb32010-05-17 22:58:03 +0200237{
238 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200239 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welted193cb32010-05-17 22:58:03 +0200240
241 if (atoi(argv[1]))
242 ggc->gtp_version = 1;
243 else
244 ggc->gtp_version = 0;
245
246 return CMD_SUCCESS;
247}
248
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800249DEFUN(cfg_ggsn_dynamic_lookup, cfg_ggsn_dynamic_lookup_cmd,
250 "ggsn dynamic",
251 GGSN_STR "Enable dynamic GRX based look-up (requires restart)\n")
252{
253 sgsn->cfg.dynamic_lookup = 1;
254 return CMD_SUCCESS;
255}
256
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800257DEFUN(cfg_grx_ggsn, cfg_grx_ggsn_cmd,
258 "grx-dns-add A.B.C.D",
259 "Add DNS server\nIPv4 address\n")
260{
261 struct ares_addr_node *node = talloc_zero(tall_bsc_ctx, struct ares_addr_node);
262 node->family = AF_INET;
263 inet_aton(argv[0], &node->addr.addr4);
264
265 node->next = sgsn->ares_servers;
266 sgsn->ares_servers = node;
267 return CMD_SUCCESS;
268}
269
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100270#define APN_STR "Configure the information per APN\n"
271#define APN_GW_STR "The APN gateway name optionally prefixed by '*' (wildcard)\n"
272
273static int add_apn_ggsn_mapping(struct vty *vty, const char *apn_str,
274 const char *imsi_prefix, int ggsn_id)
275{
276 struct apn_ctx *actx;
277 struct sgsn_ggsn_ctx *ggsn;
278
279 ggsn = sgsn_ggsn_ctx_by_id(ggsn_id);
280 if (ggsn == NULL) {
281 vty_out(vty, "%% a GGSN with id %d has not been defined%s",
282 ggsn_id, VTY_NEWLINE);
283 return CMD_WARNING;
284 }
285
286 actx = sgsn_apn_ctx_find_alloc(apn_str, imsi_prefix);
287 if (!actx) {
288 vty_out(vty, "%% unable to create APN context for %s/%s%s",
289 apn_str, imsi_prefix, VTY_NEWLINE);
290 return CMD_WARNING;
291 }
292
293 actx->ggsn = ggsn;
294
295 return CMD_SUCCESS;
296}
297
Harald Welted193cb32010-05-17 22:58:03 +0200298DEFUN(cfg_apn_ggsn, cfg_apn_ggsn_cmd,
299 "apn APNAME ggsn <0-255>",
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100300 APN_STR APN_GW_STR
301 "Select the GGSN to use when the APN gateway prefix matches\n"
302 "The GGSN id")
Harald Welted193cb32010-05-17 22:58:03 +0200303{
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100304
305 return add_apn_ggsn_mapping(vty, argv[0], "", atoi(argv[1]));
Harald Welted193cb32010-05-17 22:58:03 +0200306}
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100307
308DEFUN(cfg_apn_imsi_ggsn, cfg_apn_imsi_ggsn_cmd,
309 "apn APNAME imsi-prefix IMSIPRE ggsn <0-255>",
310 APN_STR APN_GW_STR
311 "Restrict rule to a certain IMSI prefix\n"
312 "An IMSI prefix\n"
313 "Select the GGSN to use when APN gateway and IMSI prefix match\n"
314 "The GGSN id")
315{
316
317 return add_apn_ggsn_mapping(vty, argv[0], argv[1], atoi(argv[2]));
318}
Harald Welted193cb32010-05-17 22:58:03 +0200319
320const struct value_string gprs_mm_st_strs[] = {
321 { GMM_DEREGISTERED, "DEREGISTERED" },
322 { GMM_COMMON_PROC_INIT, "COMMON PROCEDURE (INIT)" },
323 { GMM_REGISTERED_NORMAL, "REGISTERED (NORMAL)" },
Harald Weltebffeff82010-06-09 15:50:45 +0200324 { GMM_REGISTERED_SUSPENDED, "REGISTERED (SUSPENDED)" },
Harald Welted193cb32010-05-17 22:58:03 +0200325 { GMM_DEREGISTERED_INIT, "DEREGISTERED (INIT)" },
326 { 0, NULL }
327};
328
329static void vty_dump_pdp(struct vty *vty, const char *pfx,
330 struct sgsn_pdp_ctx *pdp)
331{
Jacob Erlbeck99985b52014-10-13 10:32:00 +0200332 const char *imsi = pdp->mm ? pdp->mm->imsi : "(detaching)";
Harald Welted193cb32010-05-17 22:58:03 +0200333 vty_out(vty, "%sPDP Context IMSI: %s, SAPI: %u, NSAPI: %u%s",
Jacob Erlbeck99985b52014-10-13 10:32:00 +0200334 pfx, imsi, pdp->sapi, pdp->nsapi, VTY_NEWLINE);
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200335 vty_out(vty, "%s APN: %s%s", pfx,
336 gprs_apn2str(pdp->lib->apn_use.v, pdp->lib->apn_use.l),
337 VTY_NEWLINE);
338 vty_out(vty, "%s PDP Address: %s%s", pfx,
339 gprs_pdpaddr2str(pdp->lib->eua.v, pdp->lib->eua.l),
340 VTY_NEWLINE);
Harald Welteefbdee92010-06-10 00:20:12 +0200341 vty_out_rate_ctr_group(vty, " ", pdp->ctrg);
Harald Welted193cb32010-05-17 22:58:03 +0200342}
343
344static void vty_dump_mmctx(struct vty *vty, const char *pfx,
345 struct sgsn_mm_ctx *mm, int pdp)
346{
347 vty_out(vty, "%sMM Context for IMSI %s, IMEI %s, P-TMSI %08x%s",
348 pfx, mm->imsi, mm->imei, mm->p_tmsi, VTY_NEWLINE);
Holger Hans Peter Freyther8ee13e22015-05-18 10:00:03 +0200349 vty_out(vty, "%s MSISDN: %s, TLLI: %08x%s HLR: %s",
350 pfx, mm->msisdn, mm->tlli, mm->hlr, VTY_NEWLINE);
Harald Welted193cb32010-05-17 22:58:03 +0200351 vty_out(vty, "%s MM State: %s, Routeing Area: %u-%u-%u-%u, "
352 "Cell ID: %u%s", pfx,
353 get_value_string(gprs_mm_st_strs, mm->mm_state),
354 mm->ra.mcc, mm->ra.mnc, mm->ra.lac, mm->ra.rac,
355 mm->cell_id, VTY_NEWLINE);
356
Harald Welte8acd88f2010-05-18 10:57:45 +0200357 vty_out_rate_ctr_group(vty, " ", mm->ctrg);
358
Harald Welted193cb32010-05-17 22:58:03 +0200359 if (pdp) {
360 struct sgsn_pdp_ctx *pdp;
361
362 llist_for_each_entry(pdp, &mm->pdp_list, list)
363 vty_dump_pdp(vty, " ", pdp);
364 }
365}
366
367DEFUN(show_sgsn, show_sgsn_cmd, "show sgsn",
368 SHOW_STR "Display information about the SGSN")
369{
Jacob Erlbeck80547992014-12-19 19:19:46 +0100370 if (sgsn->gsup_client) {
371 struct ipa_client_conn *link = sgsn->gsup_client->link;
372 vty_out(vty,
373 " Remote authorization: %sconnected to %s:%d via GSUP%s",
374 sgsn->gsup_client->is_connected ? "" : "not ",
375 link->addr, link->port,
376 VTY_NEWLINE);
377 }
Harald Welted193cb32010-05-17 22:58:03 +0200378 /* FIXME: statistics */
379 return CMD_SUCCESS;
380}
381
382#define MMCTX_STR "MM Context\n"
383#define INCLUDE_PDP_STR "Include PDP Context Information\n"
384
385#if 0
386DEFUN(show_mmctx_tlli, show_mmctx_tlli_cmd,
387 "show mm-context tlli HEX [pdp]",
388 SHOW_STR MMCTX_STR "Identify by TLLI\n" "TLLI\n" INCLUDE_PDP_STR)
389{
390 uint32_t tlli;
391 struct sgsn_mm_ctx *mm;
392
393 tlli = strtoul(argv[0], NULL, 16);
394 mm = sgsn_mm_ctx_by_tlli(tlli);
395 if (!mm) {
396 vty_out(vty, "No MM context for TLLI %08x%s",
397 tlli, VTY_NEWLINE);
398 return CMD_WARNING;
399 }
400 vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
401 return CMD_SUCCESS;
402}
403#endif
404
405DEFUN(swow_mmctx_imsi, show_mmctx_imsi_cmd,
406 "show mm-context imsi IMSI [pdp]",
407 SHOW_STR MMCTX_STR "Identify by IMSI\n" "IMSI of the MM Context\n"
408 INCLUDE_PDP_STR)
409{
410 struct sgsn_mm_ctx *mm;
411
412 mm = sgsn_mm_ctx_by_imsi(argv[0]);
413 if (!mm) {
414 vty_out(vty, "No MM context for IMSI %s%s",
415 argv[0], VTY_NEWLINE);
416 return CMD_WARNING;
417 }
418 vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
419 return CMD_SUCCESS;
420}
421
422DEFUN(swow_mmctx_all, show_mmctx_all_cmd,
423 "show mm-context all [pdp]",
424 SHOW_STR MMCTX_STR "All MM Contexts\n" INCLUDE_PDP_STR)
425{
426 struct sgsn_mm_ctx *mm;
427
428 llist_for_each_entry(mm, &sgsn_mm_ctxts, list)
429 vty_dump_mmctx(vty, "", mm, argv[0] ? 1 : 0);
430
431 return CMD_SUCCESS;
432}
433
Harald Welted193cb32010-05-17 22:58:03 +0200434DEFUN(show_pdpctx_all, show_pdpctx_all_cmd,
435 "show pdp-context all",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100436 SHOW_STR "Display information on PDP Context\n" "Show everything\n")
Harald Welted193cb32010-05-17 22:58:03 +0200437{
438 struct sgsn_pdp_ctx *pdp;
439
440 llist_for_each_entry(pdp, &sgsn_pdp_ctxts, g_list)
441 vty_dump_pdp(vty, "", pdp);
442
443 return CMD_SUCCESS;
444}
Harald Welte288be162010-05-01 16:48:27 +0200445
Harald Welte7f6da482013-03-19 11:00:13 +0100446
447DEFUN(imsi_acl, cfg_imsi_acl_cmd,
448 "imsi-acl (add|del) IMSI",
449 "Access Control List of foreign IMSIs\n"
450 "Add IMSI to ACL\n"
451 "Remove IMSI from ACL\n"
452 "IMSI of subscriber\n")
453{
454 const char *op = argv[0];
455 const char *imsi = argv[1];
456 int rc;
457
458 if (!strcmp(op, "add"))
Jacob Erlbeck3b5d4072014-10-24 15:11:03 +0200459 rc = sgsn_acl_add(imsi, g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +0100460 else
Jacob Erlbeck3b5d4072014-10-24 15:11:03 +0200461 rc = sgsn_acl_del(imsi, g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +0100462
463 if (rc < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100464 vty_out(vty, "%% unable to %s ACL%s", op, VTY_NEWLINE);
465
Harald Welte7f6da482013-03-19 11:00:13 +0100466 return CMD_WARNING;
467 }
468
469 return CMD_SUCCESS;
470}
471
Harald Welte3dfb5492013-03-19 11:48:54 +0100472DEFUN(cfg_auth_policy, cfg_auth_policy_cmd,
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100473 "auth-policy (accept-all|closed|acl-only|remote)",
Harald Welte3dfb5492013-03-19 11:48:54 +0100474 "Autorization Policy of SGSN\n"
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100475 "Accept all IMSIs (DANGEROUS)\n"
476 "Accept only home network subscribers or those in the ACL\n"
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100477 "Accept only subscribers in the ACL\n"
478 "Use remote subscription data only (HLR)\n")
Harald Welte3dfb5492013-03-19 11:48:54 +0100479{
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100480 int val = get_string_value(sgsn_auth_pol_strs, argv[0]);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100481 OSMO_ASSERT(val >= SGSN_AUTH_POLICY_OPEN && val <= SGSN_AUTH_POLICY_REMOTE);
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100482 g_cfg->auth_policy = val;
Jacob Erlbeck9d4f46c2014-12-17 13:20:08 +0100483 g_cfg->require_authentication = (val == SGSN_AUTH_POLICY_REMOTE);
Jacob Erlbeck771573c2014-12-19 18:08:48 +0100484 g_cfg->require_update_location = (val == SGSN_AUTH_POLICY_REMOTE);
Harald Welte3dfb5492013-03-19 11:48:54 +0100485
486 return CMD_SUCCESS;
487}
488
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100489/* Subscriber */
490#include <openbsc/gsm_subscriber.h>
491
492static void subscr_dump_full_vty(struct vty *vty, struct gsm_subscriber *subscr, int pending)
493{
494 char expire_time[200];
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100495 struct gsm_auth_tuple *at;
496 int at_idx;
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100497 struct sgsn_subscriber_pdp_data *pdp;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100498
499 vty_out(vty, " ID: %llu, Authorized: %d%s", subscr->id,
500 subscr->authorized, VTY_NEWLINE);
501 if (strlen(subscr->name))
502 vty_out(vty, " Name: '%s'%s", subscr->name, VTY_NEWLINE);
503 if (strlen(subscr->extension))
504 vty_out(vty, " Extension: %s%s", subscr->extension,
505 VTY_NEWLINE);
506 vty_out(vty, " LAC: %d/0x%x%s",
507 subscr->lac, subscr->lac, VTY_NEWLINE);
508 vty_out(vty, " IMSI: %s%s", subscr->imsi, VTY_NEWLINE);
509 if (subscr->tmsi != GSM_RESERVED_TMSI)
510 vty_out(vty, " TMSI: %08X%s", subscr->tmsi,
511 VTY_NEWLINE);
Holger Hans Peter Freytherf7b38262015-04-23 16:58:33 -0400512 if (subscr->sgsn_data->msisdn_len > 0)
513 vty_out(vty, " MSISDN (BCD): %s%s",
514 osmo_hexdump(subscr->sgsn_data->msisdn,
515 subscr->sgsn_data->msisdn_len),
516 VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100517
518 if (strlen(subscr->equipment.imei) > 0)
519 vty_out(vty, " IMEI: %s%s", subscr->equipment.imei, VTY_NEWLINE);
520
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100521 for (at_idx = 0; at_idx < ARRAY_SIZE(subscr->sgsn_data->auth_triplets);
522 at_idx++) {
523 at = &subscr->sgsn_data->auth_triplets[at_idx];
524 if (at->key_seq == GSM_KEY_SEQ_INVAL)
525 continue;
526
527 vty_out(vty, " A3A8 tuple (used %d times): ",
528 at->use_count);
529 vty_out(vty, " seq # : %d, ",
530 at->key_seq);
531 vty_out(vty, " RAND : %s, ",
532 osmo_hexdump(at->rand, sizeof(at->rand)));
533 vty_out(vty, " SRES : %s, ",
534 osmo_hexdump(at->sres, sizeof(at->sres)));
535 vty_out(vty, " Kc : %s%s",
536 osmo_hexdump(at->kc, sizeof(at->kc)),
537 VTY_NEWLINE);
538 }
539
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100540 llist_for_each_entry(pdp, &subscr->sgsn_data->pdp_list, list) {
Holger Hans Peter Freytherd05e0692015-04-23 16:59:04 -0400541 vty_out(vty, " PDP info: Id: %d, Type: 0x%04x, APN: '%s' QoS: %s%s",
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100542 pdp->context_id, pdp->pdp_type, pdp->apn_str,
Holger Hans Peter Freytherd05e0692015-04-23 16:59:04 -0400543 osmo_hexdump(pdp->qos_subscribed, pdp->qos_subscribed_len),
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100544 VTY_NEWLINE);
545 }
546
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100547 /* print the expiration time of a subscriber */
548 if (subscr->expire_lu) {
549 strftime(expire_time, sizeof(expire_time),
550 "%a, %d %b %Y %T %z", localtime(&subscr->expire_lu));
551 expire_time[sizeof(expire_time) - 1] = '\0';
552 vty_out(vty, " Expiration Time: %s%s", expire_time, VTY_NEWLINE);
553 }
554
555 if (subscr->flags)
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100556 vty_out(vty, " Flags: %s%s%s%s%s%s",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100557 subscr->flags & GSM_SUBSCRIBER_FIRST_CONTACT ?
558 "FIRST_CONTACT " : "",
559 subscr->flags & GPRS_SUBSCRIBER_CANCELLED ?
560 "CANCELLED " : "",
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100561 subscr->flags & GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING ?
562 "UPDATE_LOCATION_PENDING " : "",
563 subscr->flags & GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING ?
564 "AUTH_INFO_PENDING " : "",
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100565 subscr->flags & GPRS_SUBSCRIBER_ENABLE_PURGE ?
566 "ENABLE_PURGE " : "",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100567 VTY_NEWLINE);
568
569 vty_out(vty, " Use count: %u%s", subscr->use_count, VTY_NEWLINE);
570}
571
572DEFUN(show_subscr_cache,
573 show_subscr_cache_cmd,
574 "show subscriber cache",
575 SHOW_STR "Show information about subscribers\n"
576 "Display contents of subscriber cache\n")
577{
578 struct gsm_subscriber *subscr;
579
580 llist_for_each_entry(subscr, &active_subscribers, entry) {
581 vty_out(vty, " Subscriber:%s", VTY_NEWLINE);
582 subscr_dump_full_vty(vty, subscr, 0);
583 }
584
585 return CMD_SUCCESS;
586}
587
588#define UPDATE_SUBSCR_STR "update-subscriber imsi IMSI "
589#define UPDATE_SUBSCR_HELP "Update subscriber list\n" \
590 "Use the IMSI to select the subscriber\n" \
591 "The IMSI\n"
592
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100593#define UPDATE_SUBSCR_INSERT_HELP "Insert data into the subscriber record\n"
594
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100595DEFUN(update_subscr_insert_auth_triplet, update_subscr_insert_auth_triplet_cmd,
596 UPDATE_SUBSCR_STR "insert auth-triplet <1-5> sres SRES rand RAND kc KC",
597 UPDATE_SUBSCR_HELP
598 UPDATE_SUBSCR_INSERT_HELP
599 "Update authentication triplet\n"
600 "Triplet index\n"
601 "Set SRES value\nSRES value (4 byte) in hex\n"
602 "Set RAND value\nRAND value (16 byte) in hex\n"
603 "Set Kc value\nKc value (8 byte) in hex\n")
604{
605 const char *imsi = argv[0];
606 const int cksn = atoi(argv[1]) - 1;
607 const char *sres_str = argv[2];
608 const char *rand_str = argv[3];
609 const char *kc_str = argv[4];
610 struct gsm_auth_tuple at = {0,};
611
612 struct gsm_subscriber *subscr;
613
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100614 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100615 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100616 vty_out(vty, "%% unable get subscriber record for %s%s",
617 imsi, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100618 return CMD_WARNING;
619 }
620
621 OSMO_ASSERT(subscr->sgsn_data);
622
Jacob Erlbeck17fb3d42015-01-05 09:43:51 +0100623 if (osmo_hexparse(sres_str, &at.sres[0], sizeof(at.sres)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100624 vty_out(vty, "%% invalid SRES value '%s'%s",
625 sres_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100626 goto failed;
627 }
Jacob Erlbeck17fb3d42015-01-05 09:43:51 +0100628 if (osmo_hexparse(rand_str, &at.rand[0], sizeof(at.rand)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100629 vty_out(vty, "%% invalid RAND value '%s'%s",
630 rand_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100631 goto failed;
632 }
Jacob Erlbeck17fb3d42015-01-05 09:43:51 +0100633 if (osmo_hexparse(kc_str, &at.kc[0], sizeof(at.kc)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100634 vty_out(vty, "%% invalid Kc value '%s'%s",
635 kc_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100636 goto failed;
637 }
638 at.key_seq = cksn;
639
640 subscr->sgsn_data->auth_triplets[cksn] = at;
641 subscr->sgsn_data->auth_triplets_updated = 1;
642
643 subscr_put(subscr);
644
645 return CMD_SUCCESS;
646
647failed:
648 subscr_put(subscr);
649 return CMD_SUCCESS;
650}
651
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100652DEFUN(update_subscr_cancel, update_subscr_cancel_cmd,
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100653 UPDATE_SUBSCR_STR "cancel (update-procedure|subscription-withdraw)",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100654 UPDATE_SUBSCR_HELP
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100655 "Cancel (remove) subscriber record\n"
656 "The MS moved to another SGSN\n"
657 "The subscription is no longer valid\n")
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100658{
659 const char *imsi = argv[0];
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100660 const char *cancel_type = argv[1];
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100661
662 struct gsm_subscriber *subscr;
663
664 subscr = gprs_subscr_get_by_imsi(imsi);
665 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100666 vty_out(vty, "%% no subscriber record for %s%s",
667 imsi, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100668 return CMD_WARNING;
669 }
670
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100671 if (strcmp(cancel_type, "update-procedure") == 0)
672 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
673 else
674 subscr->sgsn_data->error_cause = GMM_CAUSE_IMPL_DETACHED;
675
Jacob Erlbeck37139e52015-01-23 13:52:55 +0100676 gprs_subscr_cancel(subscr);
677 subscr_put(subscr);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100678
679 return CMD_SUCCESS;
680}
681
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100682DEFUN(update_subscr_create, update_subscr_create_cmd,
683 UPDATE_SUBSCR_STR "create",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100684 UPDATE_SUBSCR_HELP
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100685 "Create a subscriber entry\n")
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100686{
687 const char *imsi = argv[0];
688
689 struct gsm_subscriber *subscr;
690
691 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100692 if (subscr) {
693 vty_out(vty, "%% subscriber record already exists for %s%s",
694 imsi, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100695 return CMD_WARNING;
696 }
697
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100698 subscr = gprs_subscr_get_or_create(imsi);
699 subscr->keep_in_ram = 1;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100700 subscr_put(subscr);
701
702 return CMD_SUCCESS;
703}
704
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100705DEFUN(update_subscr_destroy, update_subscr_destroy_cmd,
706 UPDATE_SUBSCR_STR "destroy",
707 UPDATE_SUBSCR_HELP
708 "Destroy a subscriber entry\n")
709{
710 const char *imsi = argv[0];
711
712 struct gsm_subscriber *subscr;
713
714 subscr = gprs_subscr_get_by_imsi(imsi);
715 if (!subscr) {
716 vty_out(vty, "%% subscriber record does not exist for %s%s",
717 imsi, VTY_NEWLINE);
718 return CMD_WARNING;
719 }
720
721 subscr->keep_in_ram = 0;
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100722 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100723 gprs_subscr_cancel(subscr);
724 if (subscr->use_count > 1)
725 vty_out(vty, "%% subscriber is still in use%s",
726 VTY_NEWLINE);
727 subscr_put(subscr);
728
729 return CMD_SUCCESS;
730}
731
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100732#define UL_ERR_STR "system-failure|data-missing|unexpected-data-value|" \
733 "unknown-subscriber|roaming-not-allowed"
734
735#define UL_ERR_HELP \
736 "Force error code SystemFailure\n" \
737 "Force error code DataMissing\n" \
738 "Force error code UnexpectedDataValue\n" \
739 "Force error code UnknownSubscriber\n" \
740 "Force error code RoamingNotAllowed\n"
741
742DEFUN(update_subscr_update_location_result, update_subscr_update_location_result_cmd,
743 UPDATE_SUBSCR_STR "update-location-result (ok|" UL_ERR_STR ")",
744 UPDATE_SUBSCR_HELP
745 "Complete the update location procedure\n"
746 "The update location request succeeded\n"
747 UL_ERR_HELP)
748{
749 const char *imsi = argv[0];
750 const char *ret_code_str = argv[1];
751
752 struct gsm_subscriber *subscr;
753
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100754 const struct value_string cause_mapping[] = {
755 { GMM_CAUSE_NET_FAIL, "system-failure" },
756 { GMM_CAUSE_INV_MAND_INFO, "data-missing" },
757 { GMM_CAUSE_PROTO_ERR_UNSPEC, "unexpected-data-value" },
758 { GMM_CAUSE_IMSI_UNKNOWN, "unknown-subscriber" },
759 { GMM_CAUSE_GPRS_NOTALLOWED, "roaming-not-allowed" },
760 { 0, NULL }
761 };
762
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100763 subscr = gprs_subscr_get_by_imsi(imsi);
764 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100765 vty_out(vty, "%% unable to get subscriber record for %s%s",
766 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100767 return CMD_WARNING;
768 }
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100769
770 if (strcmp(ret_code_str, "ok") == 0) {
771 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100772 subscr->authorized = 1;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100773 } else {
774 subscr->sgsn_data->error_cause =
775 get_string_value(cause_mapping, ret_code_str);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100776 subscr->authorized = 0;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100777 }
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100778
779 gprs_subscr_update(subscr);
780
781 subscr_put(subscr);
782
783 return CMD_SUCCESS;
784}
785
786DEFUN(update_subscr_update_auth_info, update_subscr_update_auth_info_cmd,
787 UPDATE_SUBSCR_STR "update-auth-info",
788 UPDATE_SUBSCR_HELP
789 "Complete the send authentication info procedure\n")
790{
791 const char *imsi = argv[0];
792
793 struct gsm_subscriber *subscr;
794
795 subscr = gprs_subscr_get_by_imsi(imsi);
796 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100797 vty_out(vty, "%% unable to get subscriber record for %s%s",
798 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100799 return CMD_WARNING;
800 }
801
802 gprs_subscr_update_auth_info(subscr);
803
804 subscr_put(subscr);
805
806 return CMD_SUCCESS;
807}
808
Jacob Erlbeck39f040d2014-12-18 12:46:47 +0100809DEFUN(cfg_gsup_remote_ip, cfg_gsup_remote_ip_cmd,
810 "gsup remote-ip A.B.C.D",
811 "GSUP Parameters\n"
812 "Set the IP address of the remote GSUP server\n"
813 "IPv4 Address\n")
814{
815 inet_aton(argv[0], &g_cfg->gsup_server_addr.sin_addr);
816
817 return CMD_SUCCESS;
818}
819
820DEFUN(cfg_gsup_remote_port, cfg_gsup_remote_port_cmd,
821 "gsup remote-port <0-65535>",
822 "GSUP Parameters\n"
823 "Set the TCP port of the remote GSUP server\n"
824 "Remote TCP port\n")
825{
826 g_cfg->gsup_server_port = atoi(argv[0]);
827
828 return CMD_SUCCESS;
829}
830
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +0100831DEFUN(cfg_apn_name, cfg_apn_name_cmd,
832 "access-point-name NAME",
833 "Configure a global list of allowed APNs\n"
834 "Add this NAME to the list\n")
835{
836 return add_apn_ggsn_mapping(vty, argv[0], "", 0);
837}
838
839DEFUN(cfg_no_apn_name, cfg_no_apn_name_cmd,
840 "no access-point-name NAME",
841 NO_STR "Configure a global list of allowed APNs\n"
842 "Remove entry with NAME\n")
843{
844 struct apn_ctx *apn_ctx = sgsn_apn_ctx_by_name(argv[0], "");
845 if (!apn_ctx)
846 return CMD_SUCCESS;
847
848 sgsn_apn_ctx_free(apn_ctx);
849 return CMD_SUCCESS;
850}
851
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +0200852DEFUN(cfg_cdr_filename, cfg_cdr_filename_cmd,
853 "cdr filename NAME",
854 "CDR\nSet filename\nname\n")
855{
856 talloc_free(g_cfg->cdr.filename);
857 g_cfg->cdr.filename = talloc_strdup(tall_vty_ctx, argv[0]);
858 return CMD_SUCCESS;
859}
860
861DEFUN(cfg_no_cdr_filename, cfg_no_cdr_filename_cmd,
862 "no cdr filename",
863 NO_STR "CDR\nDisable CDR generation\n")
864{
865 talloc_free(g_cfg->cdr.filename);
866 g_cfg->cdr.filename = NULL;
867 return CMD_SUCCESS;
868}
869
870DEFUN(cfg_cdr_interval, cfg_cdr_interval_cmd,
871 "cdr interval <1-2147483647>",
872 "CDR\nPDP periodic log interval\nSeconds\n")
873{
874 g_cfg->cdr.interval = atoi(argv[0]);
875 return CMD_SUCCESS;
876}
877
Harald Welte288be162010-05-01 16:48:27 +0200878int sgsn_vty_init(void)
879{
Harald Welted193cb32010-05-17 22:58:03 +0200880 install_element_ve(&show_sgsn_cmd);
881 //install_element_ve(&show_mmctx_tlli_cmd);
882 install_element_ve(&show_mmctx_imsi_cmd);
883 install_element_ve(&show_mmctx_all_cmd);
884 install_element_ve(&show_pdpctx_all_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100885 install_element_ve(&show_subscr_cache_cmd);
886
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100887 install_element(ENABLE_NODE, &update_subscr_insert_auth_triplet_cmd);
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100888 install_element(ENABLE_NODE, &update_subscr_create_cmd);
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100889 install_element(ENABLE_NODE, &update_subscr_destroy_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100890 install_element(ENABLE_NODE, &update_subscr_cancel_cmd);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100891 install_element(ENABLE_NODE, &update_subscr_update_location_result_cmd);
892 install_element(ENABLE_NODE, &update_subscr_update_auth_info_cmd);
Harald Welte288be162010-05-01 16:48:27 +0200893
894 install_element(CONFIG_NODE, &cfg_sgsn_cmd);
895 install_node(&sgsn_node, config_write_sgsn);
Jacob Erlbeck36722e12013-10-29 09:30:30 +0100896 vty_install_default(SGSN_NODE);
Harald Weltee300d002010-06-02 12:41:34 +0200897 install_element(SGSN_NODE, &cfg_sgsn_bind_addr_cmd);
Harald Welted193cb32010-05-17 22:58:03 +0200898 install_element(SGSN_NODE, &cfg_ggsn_remote_ip_cmd);
899 //install_element(SGSN_NODE, &cfg_ggsn_remote_port_cmd);
900 install_element(SGSN_NODE, &cfg_ggsn_gtp_version_cmd);
Harald Welte7f6da482013-03-19 11:00:13 +0100901 install_element(SGSN_NODE, &cfg_imsi_acl_cmd);
Harald Welte3dfb5492013-03-19 11:48:54 +0100902 install_element(SGSN_NODE, &cfg_auth_policy_cmd);
Jacob Erlbeck39f040d2014-12-18 12:46:47 +0100903 install_element(SGSN_NODE, &cfg_gsup_remote_ip_cmd);
904 install_element(SGSN_NODE, &cfg_gsup_remote_port_cmd);
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100905 install_element(SGSN_NODE, &cfg_apn_ggsn_cmd);
906 install_element(SGSN_NODE, &cfg_apn_imsi_ggsn_cmd);
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +0100907 install_element(SGSN_NODE, &cfg_apn_name_cmd);
908 install_element(SGSN_NODE, &cfg_no_apn_name_cmd);
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +0200909 install_element(SGSN_NODE, &cfg_cdr_filename_cmd);
910 install_element(SGSN_NODE, &cfg_no_cdr_filename_cmd);
911 install_element(SGSN_NODE, &cfg_cdr_interval_cmd);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800912 install_element(SGSN_NODE, &cfg_ggsn_dynamic_lookup_cmd);
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800913 install_element(SGSN_NODE, &cfg_grx_ggsn_cmd);
Harald Welte288be162010-05-01 16:48:27 +0200914
915 return 0;
916}
917
918int sgsn_parse_config(const char *config_file, struct sgsn_config *cfg)
919{
920 int rc;
921
922 g_cfg = cfg;
Harald Welte7f6da482013-03-19 11:00:13 +0100923
Harald Weltedcccb182010-05-16 20:52:23 +0200924 rc = vty_read_config_file(config_file, NULL);
Harald Welte288be162010-05-01 16:48:27 +0200925 if (rc < 0) {
926 fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
927 return rc;
928 }
929
930 return 0;
931}