blob: cc8d6c399d78039efc7e7eaa007bcfe5a41cbdaf [file] [log] [blame]
Harald Welte288be162010-05-01 16:48:27 +02001/*
Harald Welte89837d42016-05-06 23:28:11 +02002 * (C) 2010-2016 by Harald Welte <laforge@gnumonks.org>
Harald Welte288be162010-05-01 16:48:27 +02003 * (C) 2010 by On-Waves
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02004 * (C) 2015 by Holger Hans Peter Freyther
Harald Welte288be162010-05-01 16:48:27 +02005 * All Rights Reserved
6 *
7 * This program is free software; you can redistribute it and/or modify
Harald Welte9af6ddf2011-01-01 15:25:50 +01008 * it under the terms of the GNU Affero General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
Harald Welte288be162010-05-01 16:48:27 +020010 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Harald Welte9af6ddf2011-01-01 15:25:50 +010015 * GNU Affero General Public License for more details.
Harald Welte288be162010-05-01 16:48:27 +020016 *
Harald Welte9af6ddf2011-01-01 15:25:50 +010017 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
Harald Welte288be162010-05-01 16:48:27 +020019 *
20 */
21
Harald Welte288be162010-05-01 16:48:27 +020022#include <sys/socket.h>
23#include <netinet/in.h>
24#include <arpa/inet.h>
Jacob Erlbeck207f4a52014-11-11 14:01:48 +010025#include <time.h>
Harald Welte288be162010-05-01 16:48:27 +020026
Pablo Neira Ayuso136f4532011-03-22 16:47:59 +010027#include <osmocom/core/talloc.h>
28#include <osmocom/core/utils.h>
29#include <osmocom/core/rate_ctr.h>
Harald Welte53373bc2016-04-20 17:11:43 +020030#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
Harald Welte288be162010-05-01 16:48:27 +020031
32#include <openbsc/debug.h>
33#include <openbsc/sgsn.h>
Harald Welteea34a4e2012-06-16 14:59:56 +080034#include <osmocom/gprs/gprs_ns.h>
Harald Welted193cb32010-05-17 22:58:03 +020035#include <openbsc/gprs_sgsn.h>
Harald Welte62ab20c2010-05-14 18:59:17 +020036#include <openbsc/vty.h>
Neels Hofmeyreaaee922016-12-08 21:22:58 +010037#include <openbsc/gsup_client.h>
Harald Welte288be162010-05-01 16:48:27 +020038
Harald Welte4b037e42010-05-19 19:45:32 +020039#include <osmocom/vty/command.h>
40#include <osmocom/vty/vty.h>
Pablo Neira Ayuso6110a3f2011-03-28 19:35:00 +020041#include <osmocom/vty/misc.h>
Max93408ae2016-06-28 14:10:16 +020042#include <osmocom/crypt/gprs_cipher.h>
Jacob Erlbeck80547992014-12-19 19:19:46 +010043#include <osmocom/abis/ipa.h>
44
Harald Welted193cb32010-05-17 22:58:03 +020045#include <pdp.h>
46
Neels Hofmeyr2188a772016-05-20 21:59:55 +020047#include "../../bscconfig.h"
48
49#ifdef BUILD_IU
50#include <openbsc/iu.h>
51#endif
52
Harald Welte288be162010-05-01 16:48:27 +020053static struct sgsn_config *g_cfg = NULL;
54
Jacob Erlbeck106f5472014-11-04 10:08:37 +010055const struct value_string sgsn_auth_pol_strs[] = {
56 { SGSN_AUTH_POLICY_OPEN, "accept-all" },
57 { SGSN_AUTH_POLICY_CLOSED, "closed" },
58 { SGSN_AUTH_POLICY_ACL_ONLY, "acl-only" },
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +010059 { SGSN_AUTH_POLICY_REMOTE, "remote" },
Jacob Erlbeck106f5472014-11-04 10:08:37 +010060 { 0, NULL }
61};
62
Harald Welte94508822015-08-15 19:08:21 +020063/* Section 11.2.2 / Table 11.3a GPRS Mobility management timers – MS side */
64#define GSM0408_T3312_SECS (10*60) /* periodic RAU interval, default 54min */
65
66/* Section 11.2.2 / Table 11.4 MM timers netwokr side */
67#define GSM0408_T3322_SECS 6 /* DETACH_REQ -> DETACH_ACC */
68#define GSM0408_T3350_SECS 6 /* waiting for ATT/RAU/TMSI COMPL */
69#define GSM0408_T3360_SECS 6 /* waiting for AUTH/CIPH RESP */
70#define GSM0408_T3370_SECS 6 /* waiting for ID RESP */
71
Alexander Couzens5ba6fb32017-01-31 18:04:27 +010072/* Section 11.2.2 / Table 11.4a MM timers network side */
Harald Welte94508822015-08-15 19:08:21 +020073#define GSM0408_T3313_SECS 30 /* waiting for paging response */
74#define GSM0408_T3314_SECS 44 /* force to STBY on expiry, Ready timer */
75#define GSM0408_T3316_SECS 44
76
77/* Section 11.3 / Table 11.2d Timers of Session Management - network side */
78#define GSM0408_T3385_SECS 8 /* wait for ACT PDP CTX REQ */
79#define GSM0408_T3386_SECS 8 /* wait for MODIFY PDP CTX ACK */
80#define GSM0408_T3395_SECS 8 /* wait for DEACT PDP CTX ACK */
81#define GSM0408_T3397_SECS 8 /* wait for DEACT AA PDP CTX ACK */
82
83#define DECLARE_TIMER(number, doc) \
84 DEFUN(cfg_sgsn_T##number, \
85 cfg_sgsn_T##number##_cmd, \
86 "timer t" #number " <0-65535>", \
87 "Configure GPRS Timers\n" \
Holger Hans Peter Freytherfe60cfb2015-11-02 12:55:07 +010088 doc "\nTimer Value in seconds\n") \
Harald Welte94508822015-08-15 19:08:21 +020089{ \
90 int value = atoi(argv[0]); \
91 \
92 if (value < 0 || value > 65535) { \
93 vty_out(vty, "Timer value %s out of range.%s", \
94 argv[0], VTY_NEWLINE); \
95 return CMD_WARNING; \
96 } \
97 \
98 g_cfg->timers.T##number = value; \
99 return CMD_SUCCESS; \
100}
101
102DECLARE_TIMER(3312, "Periodic RA Update timer (s)")
Neels Hofmeyr65482c92015-10-19 14:37:12 +0200103DECLARE_TIMER(3322, "Detach request -> accept timer (s)")
Harald Welte94508822015-08-15 19:08:21 +0200104DECLARE_TIMER(3350, "Waiting for ATT/RAU/TMSI_COMPL timer (s)")
105DECLARE_TIMER(3360, "Waiting for AUTH/CIPH response timer (s)")
106DECLARE_TIMER(3370, "Waiting for IDENTITY response timer (s)")
107
108DECLARE_TIMER(3313, "Waiting for paging response timer (s)")
109DECLARE_TIMER(3314, "Force to STANDBY on expiry timer (s)")
Holger Hans Peter Freytherfe60cfb2015-11-02 12:55:07 +0100110DECLARE_TIMER(3316, "AA-Ready timer (s)")
Harald Welte94508822015-08-15 19:08:21 +0200111
112DECLARE_TIMER(3385, "Wait for ACT PDP CTX REQ timer (s)")
113DECLARE_TIMER(3386, "Wait for MODIFY PDP CTX ACK timer (s)")
114DECLARE_TIMER(3395, "Wait for DEACT PDP CTX ACK timer (s)")
115DECLARE_TIMER(3397, "Wait for DEACT AA PDP CTX ACK timer (s)")
116
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100117
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200118#define GSM48_MAX_APN_LEN 102 /* 10.5.6.1 */
Neels Hofmeyr30f7bcb2015-11-08 20:34:47 +0100119/* TODO: consolidate with gprs_apn_to_str(). */
120/** Copy apn to a static buffer, replacing the length octets in apn_enc with '.'
121 * and terminating with a '\0'. Return the static buffer.
122 * len: the length of the encoded APN (which has no terminating zero).
123 */
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200124static char *gprs_apn2str(uint8_t *apn, unsigned int len)
125{
126 static char apnbuf[GSM48_MAX_APN_LEN+1];
Holger Hans Peter Freyther80e03652013-07-04 18:44:16 +0200127 unsigned int i = 0;
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200128
129 if (!apn)
130 return "";
131
132 if (len > sizeof(apnbuf)-1)
133 len = sizeof(apnbuf)-1;
134
135 memcpy(apnbuf, apn, len);
136 apnbuf[len] = '\0';
137
138 /* replace the domain name step sizes with dots */
139 while (i < len) {
140 unsigned int step = apnbuf[i];
141 apnbuf[i] = '.';
142 i += step+1;
143 }
144
145 return apnbuf+1;
146}
147
Holger Hans Peter Freythera2730302014-03-23 18:08:26 +0100148char *gprs_pdpaddr2str(uint8_t *pdpa, uint8_t len)
Harald Weltec5d4a0c2010-07-02 22:47:59 +0200149{
150 static char str[INET6_ADDRSTRLEN + 10];
151
152 if (!pdpa || len < 2)
153 return "none";
154
155 switch (pdpa[0] & 0x0f) {
156 case PDP_TYPE_ORG_IETF:
157 switch (pdpa[1]) {
158 case PDP_TYPE_N_IETF_IPv4:
159 if (len < 2 + 4)
160 break;
161 strcpy(str, "IPv4 ");
162 inet_ntop(AF_INET, pdpa+2, str+5, sizeof(str)-5);
163 return str;
164 case PDP_TYPE_N_IETF_IPv6:
165 if (len < 2 + 8)
166 break;
167 strcpy(str, "IPv6 ");
168 inet_ntop(AF_INET6, pdpa+2, str+5, sizeof(str)-5);
169 return str;
170 default:
171 break;
172 }
173 break;
174 case PDP_TYPE_ORG_ETSI:
175 if (pdpa[1] == PDP_TYPE_N_ETSI_PPP)
176 return "PPP";
177 break;
178 default:
179 break;
180 }
181
182 return "invalid";
183}
184
Harald Welte288be162010-05-01 16:48:27 +0200185static struct cmd_node sgsn_node = {
186 SGSN_NODE,
Harald Welte570ce242012-08-17 13:16:10 +0200187 "%s(config-sgsn)# ",
Harald Welte288be162010-05-01 16:48:27 +0200188 1,
189};
190
191static int config_write_sgsn(struct vty *vty)
192{
Harald Welte77289c22010-05-18 14:32:29 +0200193 struct sgsn_ggsn_ctx *gctx;
Harald Welte7f6da482013-03-19 11:00:13 +0100194 struct imsi_acl_entry *acl;
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100195 struct apn_ctx *actx;
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800196 struct ares_addr_node *server;
Harald Welte288be162010-05-01 16:48:27 +0200197
198 vty_out(vty, "sgsn%s", VTY_NEWLINE);
199
Harald Weltee300d002010-06-02 12:41:34 +0200200 vty_out(vty, " gtp local-ip %s%s",
201 inet_ntoa(g_cfg->gtp_listenaddr.sin_addr), VTY_NEWLINE);
202
Harald Welted193cb32010-05-17 22:58:03 +0200203 llist_for_each_entry(gctx, &sgsn_ggsn_ctxts, list) {
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800204 if (gctx->id == UINT32_MAX)
205 continue;
206
Harald Welteff3bde82010-05-19 15:09:09 +0200207 vty_out(vty, " ggsn %u remote-ip %s%s", gctx->id,
Harald Welted193cb32010-05-17 22:58:03 +0200208 inet_ntoa(gctx->remote_addr), VTY_NEWLINE);
Harald Welteff3bde82010-05-19 15:09:09 +0200209 vty_out(vty, " ggsn %u gtp-version %u%s", gctx->id,
Harald Welted193cb32010-05-17 22:58:03 +0200210 gctx->gtp_version, VTY_NEWLINE);
Harald Welte288be162010-05-01 16:48:27 +0200211 }
212
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800213 if (sgsn->cfg.dynamic_lookup)
214 vty_out(vty, " ggsn dynamic%s", VTY_NEWLINE);
215
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800216 for (server = sgsn->ares_servers; server; server = server->next)
217 vty_out(vty, " grx-dns-add %s%s", inet_ntoa(server->addr.addr4), VTY_NEWLINE);
218
Max93408ae2016-06-28 14:10:16 +0200219 if (g_cfg->cipher != GPRS_ALGO_GEA0)
220 vty_out(vty, " encryption %s%s",
221 get_value_string(gprs_cipher_names, g_cfg->cipher),
222 VTY_NEWLINE);
Jacob Erlbeck39f040d2014-12-18 12:46:47 +0100223 if (g_cfg->gsup_server_addr.sin_addr.s_addr)
224 vty_out(vty, " gsup remote-ip %s%s",
225 inet_ntoa(g_cfg->gsup_server_addr.sin_addr), VTY_NEWLINE);
226 if (g_cfg->gsup_server_port)
227 vty_out(vty, " gsup remote-port %d%s",
228 g_cfg->gsup_server_port, VTY_NEWLINE);
Max176b62a2016-07-04 11:09:07 +0200229 vty_out(vty, " auth-policy %s%s",
230 get_value_string(sgsn_auth_pol_strs, g_cfg->auth_policy),
231 VTY_NEWLINE);
Neels Hofmeyr568a7272015-10-12 11:57:38 +0200232
233 vty_out(vty, " gsup oap-id %d%s",
234 (int)g_cfg->oap.client_id, VTY_NEWLINE);
235 if (g_cfg->oap.secret_k_present != 0)
236 vty_out(vty, " gsup oap-k %s%s",
237 osmo_hexdump_nospc(g_cfg->oap.secret_k, sizeof(g_cfg->oap.secret_k)),
238 VTY_NEWLINE);
239 if (g_cfg->oap.secret_opc_present != 0)
240 vty_out(vty, " gsup oap-opc %s%s",
241 osmo_hexdump_nospc(g_cfg->oap.secret_opc, sizeof(g_cfg->oap.secret_opc)),
242 VTY_NEWLINE);
243
Harald Welte7f6da482013-03-19 11:00:13 +0100244 llist_for_each_entry(acl, &g_cfg->imsi_acl, list)
245 vty_out(vty, " imsi-acl add %s%s", acl->imsi, VTY_NEWLINE);
246
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100247 if (llist_empty(&sgsn_apn_ctxts))
248 vty_out(vty, " ! apn * ggsn 0%s", VTY_NEWLINE);
249 llist_for_each_entry(actx, &sgsn_apn_ctxts, list) {
250 if (strlen(actx->imsi_prefix) > 0)
Holger Hans Peter Freytherb7ae0b32015-05-29 15:11:55 +0200251 vty_out(vty, " apn %s imsi-prefix %s ggsn %u%s",
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100252 actx->name, actx->imsi_prefix, actx->ggsn->id,
253 VTY_NEWLINE);
254 else
Holger Hans Peter Freytherb7ae0b32015-05-29 15:11:55 +0200255 vty_out(vty, " apn %s ggsn %u%s", actx->name,
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100256 actx->ggsn->id, VTY_NEWLINE);
257 }
258
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +0200259 if (g_cfg->cdr.filename)
260 vty_out(vty, " cdr filename %s%s", g_cfg->cdr.filename, VTY_NEWLINE);
261 else
262 vty_out(vty, " no cdr filename%s", VTY_NEWLINE);
263 vty_out(vty, " cdr interval %d%s", g_cfg->cdr.interval, VTY_NEWLINE);
264
Harald Welte94508822015-08-15 19:08:21 +0200265 vty_out(vty, " timer t3312 %d%s", g_cfg->timers.T3312, VTY_NEWLINE);
266 vty_out(vty, " timer t3322 %d%s", g_cfg->timers.T3322, VTY_NEWLINE);
267 vty_out(vty, " timer t3350 %d%s", g_cfg->timers.T3350, VTY_NEWLINE);
268 vty_out(vty, " timer t3360 %d%s", g_cfg->timers.T3360, VTY_NEWLINE);
269 vty_out(vty, " timer t3370 %d%s", g_cfg->timers.T3370, VTY_NEWLINE);
270 vty_out(vty, " timer t3313 %d%s", g_cfg->timers.T3313, VTY_NEWLINE);
271 vty_out(vty, " timer t3314 %d%s", g_cfg->timers.T3314, VTY_NEWLINE);
272 vty_out(vty, " timer t3316 %d%s", g_cfg->timers.T3316, VTY_NEWLINE);
273 vty_out(vty, " timer t3385 %d%s", g_cfg->timers.T3385, VTY_NEWLINE);
274 vty_out(vty, " timer t3386 %d%s", g_cfg->timers.T3386, VTY_NEWLINE);
275 vty_out(vty, " timer t3395 %d%s", g_cfg->timers.T3395, VTY_NEWLINE);
276 vty_out(vty, " timer t3397 %d%s", g_cfg->timers.T3397, VTY_NEWLINE);
277
Philippf1f34362016-08-26 17:00:21 +0200278 if (g_cfg->pcomp_rfc1144.active) {
279 vty_out(vty, " compression rfc1144 active slots %d%s",
280 g_cfg->pcomp_rfc1144.s01 + 1, VTY_NEWLINE);
281 } else if (g_cfg->pcomp_rfc1144.passive) {
282 vty_out(vty, " compression rfc1144 passive%s", VTY_NEWLINE);
283 } else
284 vty_out(vty, " no compression rfc1144%s", VTY_NEWLINE);
285
Philipp73f83d52016-09-02 13:38:01 +0200286 if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 1) {
287 vty_out(vty,
288 " compression v42bis active direction sgsn codewords %d strlen %d%s",
289 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
290 VTY_NEWLINE);
291 } else if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 2) {
292 vty_out(vty,
293 " compression v42bis active direction ms codewords %d strlen %d%s",
294 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
295 VTY_NEWLINE);
296 } else if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 3) {
297 vty_out(vty,
298 " compression v42bis active direction both codewords %d strlen %d%s",
299 g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
300 VTY_NEWLINE);
301 } else if (g_cfg->dcomp_v42bis.passive) {
302 vty_out(vty, " compression v42bis passive%s", VTY_NEWLINE);
303 } else
304 vty_out(vty, " no compression v42bis%s", VTY_NEWLINE);
305
Neels Hofmeyr2188a772016-05-20 21:59:55 +0200306#ifdef BUILD_IU
307 iu_vty_config_write(vty, " ");
308#endif
309
Harald Welte288be162010-05-01 16:48:27 +0200310 return CMD_SUCCESS;
311}
312
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100313#define SGSN_STR "Configure the SGSN\n"
314#define GGSN_STR "Configure the GGSN information\n"
Harald Weltee300d002010-06-02 12:41:34 +0200315
316DEFUN(cfg_sgsn, cfg_sgsn_cmd,
317 "sgsn",
318 SGSN_STR)
Harald Welte288be162010-05-01 16:48:27 +0200319{
320 vty->node = SGSN_NODE;
321 return CMD_SUCCESS;
322}
323
Harald Weltee300d002010-06-02 12:41:34 +0200324DEFUN(cfg_sgsn_bind_addr, cfg_sgsn_bind_addr_cmd,
325 "gtp local-ip A.B.C.D",
326 "GTP Parameters\n"
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100327 "Set the IP address for the local GTP bind\n"
328 "IPv4 Address\n")
Harald Weltee300d002010-06-02 12:41:34 +0200329{
330 inet_aton(argv[0], &g_cfg->gtp_listenaddr.sin_addr);
331
332 return CMD_SUCCESS;
333}
334
Harald Welted193cb32010-05-17 22:58:03 +0200335DEFUN(cfg_ggsn_remote_ip, cfg_ggsn_remote_ip_cmd,
336 "ggsn <0-255> remote-ip A.B.C.D",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100337 GGSN_STR "GGSN Number\n" IP_STR "IPv4 Address\n")
Harald Welted193cb32010-05-17 22:58:03 +0200338{
339 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200340 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welte288be162010-05-01 16:48:27 +0200341
Harald Welted193cb32010-05-17 22:58:03 +0200342 inet_aton(argv[1], &ggc->remote_addr);
Harald Welte288be162010-05-01 16:48:27 +0200343
Harald Welted193cb32010-05-17 22:58:03 +0200344 return CMD_SUCCESS;
345}
346
347#if 0
348DEFUN(cfg_ggsn_remote_port, cfg_ggsn_remote_port_cmd,
349 "ggsn <0-255> remote-port <0-65535>",
350 "")
351{
352 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200353 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welted193cb32010-05-17 22:58:03 +0200354 uint16_t port = atoi(argv[1]);
355
356}
357#endif
358
359DEFUN(cfg_ggsn_gtp_version, cfg_ggsn_gtp_version_cmd,
360 "ggsn <0-255> gtp-version (0|1)",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100361 GGSN_STR "GGSN Number\n" "GTP Version\n"
362 "Version 0\n" "Version 1\n")
Harald Welted193cb32010-05-17 22:58:03 +0200363{
364 uint32_t id = atoi(argv[0]);
Harald Welte77289c22010-05-18 14:32:29 +0200365 struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
Harald Welted193cb32010-05-17 22:58:03 +0200366
367 if (atoi(argv[1]))
368 ggc->gtp_version = 1;
369 else
370 ggc->gtp_version = 0;
371
372 return CMD_SUCCESS;
373}
374
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +0800375DEFUN(cfg_ggsn_dynamic_lookup, cfg_ggsn_dynamic_lookup_cmd,
376 "ggsn dynamic",
377 GGSN_STR "Enable dynamic GRX based look-up (requires restart)\n")
378{
379 sgsn->cfg.dynamic_lookup = 1;
380 return CMD_SUCCESS;
381}
382
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +0800383DEFUN(cfg_grx_ggsn, cfg_grx_ggsn_cmd,
384 "grx-dns-add A.B.C.D",
385 "Add DNS server\nIPv4 address\n")
386{
387 struct ares_addr_node *node = talloc_zero(tall_bsc_ctx, struct ares_addr_node);
388 node->family = AF_INET;
389 inet_aton(argv[0], &node->addr.addr4);
390
391 node->next = sgsn->ares_servers;
392 sgsn->ares_servers = node;
393 return CMD_SUCCESS;
394}
395
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100396#define APN_STR "Configure the information per APN\n"
397#define APN_GW_STR "The APN gateway name optionally prefixed by '*' (wildcard)\n"
398
399static int add_apn_ggsn_mapping(struct vty *vty, const char *apn_str,
400 const char *imsi_prefix, int ggsn_id)
401{
402 struct apn_ctx *actx;
403 struct sgsn_ggsn_ctx *ggsn;
404
405 ggsn = sgsn_ggsn_ctx_by_id(ggsn_id);
406 if (ggsn == NULL) {
407 vty_out(vty, "%% a GGSN with id %d has not been defined%s",
408 ggsn_id, VTY_NEWLINE);
409 return CMD_WARNING;
410 }
411
412 actx = sgsn_apn_ctx_find_alloc(apn_str, imsi_prefix);
413 if (!actx) {
414 vty_out(vty, "%% unable to create APN context for %s/%s%s",
415 apn_str, imsi_prefix, VTY_NEWLINE);
416 return CMD_WARNING;
417 }
418
419 actx->ggsn = ggsn;
420
421 return CMD_SUCCESS;
422}
423
Harald Welted193cb32010-05-17 22:58:03 +0200424DEFUN(cfg_apn_ggsn, cfg_apn_ggsn_cmd,
425 "apn APNAME ggsn <0-255>",
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100426 APN_STR APN_GW_STR
427 "Select the GGSN to use when the APN gateway prefix matches\n"
428 "The GGSN id")
Harald Welted193cb32010-05-17 22:58:03 +0200429{
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100430
431 return add_apn_ggsn_mapping(vty, argv[0], "", atoi(argv[1]));
Harald Welted193cb32010-05-17 22:58:03 +0200432}
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +0100433
434DEFUN(cfg_apn_imsi_ggsn, cfg_apn_imsi_ggsn_cmd,
435 "apn APNAME imsi-prefix IMSIPRE ggsn <0-255>",
436 APN_STR APN_GW_STR
437 "Restrict rule to a certain IMSI prefix\n"
438 "An IMSI prefix\n"
439 "Select the GGSN to use when APN gateway and IMSI prefix match\n"
440 "The GGSN id")
441{
442
443 return add_apn_ggsn_mapping(vty, argv[0], argv[1], atoi(argv[2]));
444}
Harald Welted193cb32010-05-17 22:58:03 +0200445
446const struct value_string gprs_mm_st_strs[] = {
447 { GMM_DEREGISTERED, "DEREGISTERED" },
448 { GMM_COMMON_PROC_INIT, "COMMON PROCEDURE (INIT)" },
449 { GMM_REGISTERED_NORMAL, "REGISTERED (NORMAL)" },
Harald Weltebffeff82010-06-09 15:50:45 +0200450 { GMM_REGISTERED_SUSPENDED, "REGISTERED (SUSPENDED)" },
Harald Welted193cb32010-05-17 22:58:03 +0200451 { GMM_DEREGISTERED_INIT, "DEREGISTERED (INIT)" },
452 { 0, NULL }
453};
454
Harald Welte471ac7d2016-12-15 19:48:58 +0100455static char *gtp_ntoa(struct ul16_t *ul)
456{
457 if (ul->l == 4) {
458 struct in_addr *ia = (struct in_addr *) ul;
459 return inet_ntoa(*ia);
460 } else {
461 return "UNKNOWN";
462 }
463}
464
Harald Welted193cb32010-05-17 22:58:03 +0200465static void vty_dump_pdp(struct vty *vty, const char *pfx,
466 struct sgsn_pdp_ctx *pdp)
467{
Jacob Erlbeck99985b52014-10-13 10:32:00 +0200468 const char *imsi = pdp->mm ? pdp->mm->imsi : "(detaching)";
Harald Welte471ac7d2016-12-15 19:48:58 +0100469 vty_out(vty, "%sPDP Context IMSI: %s, SAPI: %u, NSAPI: %u, TI: %u%s",
470 pfx, imsi, pdp->sapi, pdp->nsapi, pdp->ti, VTY_NEWLINE);
Harald Weltedfbd2c82017-08-13 00:56:45 +0200471 if (pdp->lib) {
472 vty_out(vty, "%s APN: %s%s", pfx,
473 gprs_apn2str(pdp->lib->apn_use.v, pdp->lib->apn_use.l),
474 VTY_NEWLINE);
475 vty_out(vty, "%s PDP Address: %s%s", pfx,
476 gprs_pdpaddr2str(pdp->lib->eua.v, pdp->lib->eua.l),
477 VTY_NEWLINE);
478 vty_out(vty, "%s GTP Local Control(%s / TEIC: 0x%08x) ", pfx,
479 gtp_ntoa(&pdp->lib->gsnlc), pdp->lib->teic_own);
480 vty_out(vty, "Data(%s / TEID: 0x%08x)%s",
481 gtp_ntoa(&pdp->lib->gsnlu), pdp->lib->teid_own, VTY_NEWLINE);
482 vty_out(vty, "%s GTP Remote Control(%s / TEIC: 0x%08x) ", pfx,
483 gtp_ntoa(&pdp->lib->gsnrc), pdp->lib->teic_gn);
484 vty_out(vty, "Data(%s / TEID: 0x%08x)%s",
485 gtp_ntoa(&pdp->lib->gsnru), pdp->lib->teid_gn, VTY_NEWLINE);
486 }
Harald Welte471ac7d2016-12-15 19:48:58 +0100487
Harald Welteefbdee92010-06-10 00:20:12 +0200488 vty_out_rate_ctr_group(vty, " ", pdp->ctrg);
Harald Welted193cb32010-05-17 22:58:03 +0200489}
490
491static void vty_dump_mmctx(struct vty *vty, const char *pfx,
492 struct sgsn_mm_ctx *mm, int pdp)
493{
494 vty_out(vty, "%sMM Context for IMSI %s, IMEI %s, P-TMSI %08x%s",
495 pfx, mm->imsi, mm->imei, mm->p_tmsi, VTY_NEWLINE);
Holger Hans Peter Freyther8ee13e22015-05-18 10:00:03 +0200496 vty_out(vty, "%s MSISDN: %s, TLLI: %08x%s HLR: %s",
Harald Weltef97ee042015-12-25 19:12:21 +0100497 pfx, mm->msisdn, mm->gb.tlli, mm->hlr, VTY_NEWLINE);
Harald Welted193cb32010-05-17 22:58:03 +0200498 vty_out(vty, "%s MM State: %s, Routeing Area: %u-%u-%u-%u, "
499 "Cell ID: %u%s", pfx,
Alexander Couzens4f8da6d2017-01-31 15:34:26 +0100500 get_value_string(gprs_mm_st_strs, mm->gmm_state),
Harald Welted193cb32010-05-17 22:58:03 +0200501 mm->ra.mcc, mm->ra.mnc, mm->ra.lac, mm->ra.rac,
Harald Weltef97ee042015-12-25 19:12:21 +0100502 mm->gb.cell_id, VTY_NEWLINE);
Harald Welted193cb32010-05-17 22:58:03 +0200503
Harald Welte8acd88f2010-05-18 10:57:45 +0200504 vty_out_rate_ctr_group(vty, " ", mm->ctrg);
505
Harald Welted193cb32010-05-17 22:58:03 +0200506 if (pdp) {
507 struct sgsn_pdp_ctx *pdp;
508
509 llist_for_each_entry(pdp, &mm->pdp_list, list)
510 vty_dump_pdp(vty, " ", pdp);
511 }
512}
513
514DEFUN(show_sgsn, show_sgsn_cmd, "show sgsn",
515 SHOW_STR "Display information about the SGSN")
516{
Jacob Erlbeck80547992014-12-19 19:19:46 +0100517 if (sgsn->gsup_client) {
518 struct ipa_client_conn *link = sgsn->gsup_client->link;
519 vty_out(vty,
520 " Remote authorization: %sconnected to %s:%d via GSUP%s",
521 sgsn->gsup_client->is_connected ? "" : "not ",
522 link->addr, link->port,
523 VTY_NEWLINE);
524 }
Harald Welted193cb32010-05-17 22:58:03 +0200525 /* FIXME: statistics */
526 return CMD_SUCCESS;
527}
528
529#define MMCTX_STR "MM Context\n"
530#define INCLUDE_PDP_STR "Include PDP Context Information\n"
531
532#if 0
533DEFUN(show_mmctx_tlli, show_mmctx_tlli_cmd,
534 "show mm-context tlli HEX [pdp]",
535 SHOW_STR MMCTX_STR "Identify by TLLI\n" "TLLI\n" INCLUDE_PDP_STR)
536{
537 uint32_t tlli;
538 struct sgsn_mm_ctx *mm;
539
540 tlli = strtoul(argv[0], NULL, 16);
541 mm = sgsn_mm_ctx_by_tlli(tlli);
542 if (!mm) {
543 vty_out(vty, "No MM context for TLLI %08x%s",
544 tlli, VTY_NEWLINE);
545 return CMD_WARNING;
546 }
547 vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
548 return CMD_SUCCESS;
549}
550#endif
551
552DEFUN(swow_mmctx_imsi, show_mmctx_imsi_cmd,
553 "show mm-context imsi IMSI [pdp]",
554 SHOW_STR MMCTX_STR "Identify by IMSI\n" "IMSI of the MM Context\n"
555 INCLUDE_PDP_STR)
556{
557 struct sgsn_mm_ctx *mm;
558
559 mm = sgsn_mm_ctx_by_imsi(argv[0]);
560 if (!mm) {
561 vty_out(vty, "No MM context for IMSI %s%s",
562 argv[0], VTY_NEWLINE);
563 return CMD_WARNING;
564 }
565 vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
566 return CMD_SUCCESS;
567}
568
569DEFUN(swow_mmctx_all, show_mmctx_all_cmd,
570 "show mm-context all [pdp]",
571 SHOW_STR MMCTX_STR "All MM Contexts\n" INCLUDE_PDP_STR)
572{
573 struct sgsn_mm_ctx *mm;
574
575 llist_for_each_entry(mm, &sgsn_mm_ctxts, list)
576 vty_dump_mmctx(vty, "", mm, argv[0] ? 1 : 0);
577
578 return CMD_SUCCESS;
579}
580
Harald Welted193cb32010-05-17 22:58:03 +0200581DEFUN(show_pdpctx_all, show_pdpctx_all_cmd,
582 "show pdp-context all",
Holger Hans Peter Freyther1491f2e2011-11-05 15:21:16 +0100583 SHOW_STR "Display information on PDP Context\n" "Show everything\n")
Harald Welted193cb32010-05-17 22:58:03 +0200584{
585 struct sgsn_pdp_ctx *pdp;
586
587 llist_for_each_entry(pdp, &sgsn_pdp_ctxts, g_list)
588 vty_dump_pdp(vty, "", pdp);
589
590 return CMD_SUCCESS;
591}
Harald Welte288be162010-05-01 16:48:27 +0200592
Harald Welte7f6da482013-03-19 11:00:13 +0100593
594DEFUN(imsi_acl, cfg_imsi_acl_cmd,
595 "imsi-acl (add|del) IMSI",
596 "Access Control List of foreign IMSIs\n"
597 "Add IMSI to ACL\n"
598 "Remove IMSI from ACL\n"
599 "IMSI of subscriber\n")
600{
Philipp Maier6ee49d82017-02-28 16:53:07 +0100601 char imsi_sanitized[GSM23003_IMSI_MAX_DIGITS+1];
Harald Welte7f6da482013-03-19 11:00:13 +0100602 const char *op = argv[0];
Philipp Maier6ee49d82017-02-28 16:53:07 +0100603 const char *imsi = imsi_sanitized;
Harald Welte7f6da482013-03-19 11:00:13 +0100604 int rc;
605
Philipp Maier6ee49d82017-02-28 16:53:07 +0100606 /* Sanitize IMSI */
607 if (strlen(argv[1]) > GSM23003_IMSI_MAX_DIGITS) {
608 vty_out(vty, "%% IMSI (%s) too long -- ignored!%s",
609 argv[1], VTY_NEWLINE);
610 return CMD_WARNING;
611 }
612 memset(imsi_sanitized, '0', sizeof(imsi_sanitized));
613 strcpy(imsi_sanitized+GSM23003_IMSI_MAX_DIGITS-strlen(argv[1]),argv[1]);
614
Harald Welte7f6da482013-03-19 11:00:13 +0100615 if (!strcmp(op, "add"))
Jacob Erlbeck3b5d4072014-10-24 15:11:03 +0200616 rc = sgsn_acl_add(imsi, g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +0100617 else
Jacob Erlbeck3b5d4072014-10-24 15:11:03 +0200618 rc = sgsn_acl_del(imsi, g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +0100619
620 if (rc < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100621 vty_out(vty, "%% unable to %s ACL%s", op, VTY_NEWLINE);
Harald Welte7f6da482013-03-19 11:00:13 +0100622 return CMD_WARNING;
623 }
624
625 return CMD_SUCCESS;
626}
627
Max93408ae2016-06-28 14:10:16 +0200628DEFUN(cfg_encrypt, cfg_encrypt_cmd,
629 "encryption (GEA0|GEA1|GEA2|GEA3|GEA4)",
630 "Set encryption algorithm for SGSN\n"
631 "Use GEA0 (no encryption)\n"
632 "Use GEA1\nUse GEA2\nUse GEA3\nUse GEA4\n")
633{
Max93408ae2016-06-28 14:10:16 +0200634 enum gprs_ciph_algo c = get_string_value(gprs_cipher_names, argv[0]);
Max086067f2017-05-02 13:03:28 +0200635 if (c != GPRS_ALGO_GEA0) {
636 if (!gprs_cipher_supported(c)) {
637 vty_out(vty, "%% cipher %s is unsupported in current version%s", argv[0], VTY_NEWLINE);
638 return CMD_WARNING;
639 }
640
641 if (!g_cfg->require_authentication) {
642 vty_out(vty, "%% unable to use encryption %s without authentication: please adjust auth-policy%s",
643 argv[0], VTY_NEWLINE);
644 return CMD_WARNING;
645 }
Max93408ae2016-06-28 14:10:16 +0200646 }
647
648 g_cfg->cipher = c;
649
650 return CMD_SUCCESS;
651}
652
Harald Welte3dfb5492013-03-19 11:48:54 +0100653DEFUN(cfg_auth_policy, cfg_auth_policy_cmd,
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100654 "auth-policy (accept-all|closed|acl-only|remote)",
Harald Welte3dfb5492013-03-19 11:48:54 +0100655 "Autorization Policy of SGSN\n"
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100656 "Accept all IMSIs (DANGEROUS)\n"
657 "Accept only home network subscribers or those in the ACL\n"
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100658 "Accept only subscribers in the ACL\n"
659 "Use remote subscription data only (HLR)\n")
Harald Welte3dfb5492013-03-19 11:48:54 +0100660{
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100661 int val = get_string_value(sgsn_auth_pol_strs, argv[0]);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100662 OSMO_ASSERT(val >= SGSN_AUTH_POLICY_OPEN && val <= SGSN_AUTH_POLICY_REMOTE);
Jacob Erlbeck106f5472014-11-04 10:08:37 +0100663 g_cfg->auth_policy = val;
Jacob Erlbeck9d4f46c2014-12-17 13:20:08 +0100664 g_cfg->require_authentication = (val == SGSN_AUTH_POLICY_REMOTE);
Jacob Erlbeck771573c2014-12-19 18:08:48 +0100665 g_cfg->require_update_location = (val == SGSN_AUTH_POLICY_REMOTE);
Harald Welte3dfb5492013-03-19 11:48:54 +0100666
667 return CMD_SUCCESS;
668}
669
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100670/* Subscriber */
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100671#include <openbsc/gprs_subscriber.h>
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100672
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100673static void subscr_dump_full_vty(struct vty *vty, struct gprs_subscr *gsub, int pending)
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100674{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100675#if 0
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100676 char expire_time[200];
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100677#endif
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100678 struct gsm_auth_tuple *at;
679 int at_idx;
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100680 struct sgsn_subscriber_pdp_data *pdp;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100681
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100682 vty_out(vty, " Authorized: %d%s",
683 gsub->authorized, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100684 vty_out(vty, " LAC: %d/0x%x%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100685 gsub->lac, gsub->lac, VTY_NEWLINE);
686 vty_out(vty, " IMSI: %s%s", gsub->imsi, VTY_NEWLINE);
687 if (gsub->tmsi != GSM_RESERVED_TMSI)
688 vty_out(vty, " TMSI: %08X%s", gsub->tmsi,
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100689 VTY_NEWLINE);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100690 if (gsub->sgsn_data->msisdn_len > 0)
Holger Hans Peter Freytherf7b38262015-04-23 16:58:33 -0400691 vty_out(vty, " MSISDN (BCD): %s%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100692 osmo_hexdump(gsub->sgsn_data->msisdn,
693 gsub->sgsn_data->msisdn_len),
Holger Hans Peter Freytherf7b38262015-04-23 16:58:33 -0400694 VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100695
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100696 if (strlen(gsub->imei) > 0)
697 vty_out(vty, " IMEI: %s%s", gsub->imei, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100698
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100699 for (at_idx = 0; at_idx < ARRAY_SIZE(gsub->sgsn_data->auth_triplets);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100700 at_idx++) {
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100701 at = &gsub->sgsn_data->auth_triplets[at_idx];
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100702 if (at->key_seq == GSM_KEY_SEQ_INVAL)
703 continue;
704
705 vty_out(vty, " A3A8 tuple (used %d times): ",
706 at->use_count);
Harald Welte89837d42016-05-06 23:28:11 +0200707 vty_out(vty, " CKSN: %d, ",
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100708 at->key_seq);
Harald Welte89837d42016-05-06 23:28:11 +0200709 if (at->vec.auth_types & OSMO_AUTH_TYPE_GSM) {
710 vty_out(vty, "RAND: %s, ",
711 osmo_hexdump(at->vec.rand,
712 sizeof(at->vec.rand)));
713 vty_out(vty, "SRES: %s, ",
714 osmo_hexdump(at->vec.sres,
715 sizeof(at->vec.sres)));
716 vty_out(vty, "Kc: %s%s",
717 osmo_hexdump(at->vec.kc,
718 sizeof(at->vec.kc)), VTY_NEWLINE);
719 }
720 if (at->vec.auth_types & OSMO_AUTH_TYPE_UMTS) {
721 vty_out(vty, " AUTN: %s, ",
722 osmo_hexdump(at->vec.autn,
723 sizeof(at->vec.autn)));
724 vty_out(vty, "RES: %s, ",
725 osmo_hexdump(at->vec.res, at->vec.res_len));
726 vty_out(vty, "IK: %s, ",
727 osmo_hexdump(at->vec.ik, sizeof(at->vec.ik)));
728 vty_out(vty, "CK: %s, ",
729 osmo_hexdump(at->vec.ck, sizeof(at->vec.ck)));
730 }
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100731 }
732
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100733 llist_for_each_entry(pdp, &gsub->sgsn_data->pdp_list, list) {
Holger Hans Peter Freytherd05e0692015-04-23 16:59:04 -0400734 vty_out(vty, " PDP info: Id: %d, Type: 0x%04x, APN: '%s' QoS: %s%s",
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100735 pdp->context_id, pdp->pdp_type, pdp->apn_str,
Holger Hans Peter Freytherd05e0692015-04-23 16:59:04 -0400736 osmo_hexdump(pdp->qos_subscribed, pdp->qos_subscribed_len),
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100737 VTY_NEWLINE);
738 }
739
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100740#if 0
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100741 /* print the expiration time of a subscriber */
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100742 if (gsub->expire_lu) {
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100743 strftime(expire_time, sizeof(expire_time),
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100744 "%a, %d %b %Y %T %z", localtime(&gsub->expire_lu));
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100745 expire_time[sizeof(expire_time) - 1] = '\0';
746 vty_out(vty, " Expiration Time: %s%s", expire_time, VTY_NEWLINE);
747 }
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100748#endif
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100749
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100750 if (gsub->flags)
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100751 vty_out(vty, " Flags: %s%s%s%s%s%s",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100752 gsub->flags & GPRS_SUBSCRIBER_FIRST_CONTACT ?
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100753 "FIRST_CONTACT " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100754 gsub->flags & GPRS_SUBSCRIBER_CANCELLED ?
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100755 "CANCELLED " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100756 gsub->flags & GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING ?
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100757 "UPDATE_LOCATION_PENDING " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100758 gsub->flags & GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING ?
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100759 "AUTH_INFO_PENDING " : "",
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100760 gsub->flags & GPRS_SUBSCRIBER_ENABLE_PURGE ?
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100761 "ENABLE_PURGE " : "",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100762 VTY_NEWLINE);
763
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100764 vty_out(vty, " Use count: %u%s", gsub->use_count, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100765}
766
767DEFUN(show_subscr_cache,
768 show_subscr_cache_cmd,
769 "show subscriber cache",
770 SHOW_STR "Show information about subscribers\n"
771 "Display contents of subscriber cache\n")
772{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100773 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100774
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100775 llist_for_each_entry(subscr, gprs_subscribers, entry) {
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100776 vty_out(vty, " Subscriber:%s", VTY_NEWLINE);
777 subscr_dump_full_vty(vty, subscr, 0);
778 }
779
780 return CMD_SUCCESS;
781}
782
783#define UPDATE_SUBSCR_STR "update-subscriber imsi IMSI "
784#define UPDATE_SUBSCR_HELP "Update subscriber list\n" \
785 "Use the IMSI to select the subscriber\n" \
786 "The IMSI\n"
787
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100788#define UPDATE_SUBSCR_INSERT_HELP "Insert data into the subscriber record\n"
789
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100790DEFUN(update_subscr_insert_auth_triplet, update_subscr_insert_auth_triplet_cmd,
791 UPDATE_SUBSCR_STR "insert auth-triplet <1-5> sres SRES rand RAND kc KC",
792 UPDATE_SUBSCR_HELP
793 UPDATE_SUBSCR_INSERT_HELP
794 "Update authentication triplet\n"
795 "Triplet index\n"
796 "Set SRES value\nSRES value (4 byte) in hex\n"
797 "Set RAND value\nRAND value (16 byte) in hex\n"
798 "Set Kc value\nKc value (8 byte) in hex\n")
799{
800 const char *imsi = argv[0];
801 const int cksn = atoi(argv[1]) - 1;
802 const char *sres_str = argv[2];
803 const char *rand_str = argv[3];
804 const char *kc_str = argv[4];
805 struct gsm_auth_tuple at = {0,};
806
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100807 struct gprs_subscr *subscr;
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100808
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100809 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100810 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100811 vty_out(vty, "%% unable get subscriber record for %s%s",
812 imsi, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100813 return CMD_WARNING;
814 }
815
816 OSMO_ASSERT(subscr->sgsn_data);
817
Harald Welte121e9a42016-04-20 13:13:19 +0200818 if (osmo_hexparse(sres_str, &at.vec.sres[0], sizeof(at.vec.sres)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100819 vty_out(vty, "%% invalid SRES value '%s'%s",
820 sres_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100821 goto failed;
822 }
Harald Welte121e9a42016-04-20 13:13:19 +0200823 if (osmo_hexparse(rand_str, &at.vec.rand[0], sizeof(at.vec.rand)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100824 vty_out(vty, "%% invalid RAND value '%s'%s",
825 rand_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100826 goto failed;
827 }
Harald Welte121e9a42016-04-20 13:13:19 +0200828 if (osmo_hexparse(kc_str, &at.vec.kc[0], sizeof(at.vec.kc)) < 0) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100829 vty_out(vty, "%% invalid Kc value '%s'%s",
830 kc_str, VTY_NEWLINE);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100831 goto failed;
832 }
833 at.key_seq = cksn;
834
835 subscr->sgsn_data->auth_triplets[cksn] = at;
836 subscr->sgsn_data->auth_triplets_updated = 1;
837
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100838 gprs_subscr_put(subscr);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100839
840 return CMD_SUCCESS;
841
842failed:
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100843 gprs_subscr_put(subscr);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100844 return CMD_SUCCESS;
845}
846
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100847DEFUN(update_subscr_cancel, update_subscr_cancel_cmd,
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100848 UPDATE_SUBSCR_STR "cancel (update-procedure|subscription-withdraw)",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100849 UPDATE_SUBSCR_HELP
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100850 "Cancel (remove) subscriber record\n"
851 "The MS moved to another SGSN\n"
852 "The subscription is no longer valid\n")
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100853{
854 const char *imsi = argv[0];
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100855 const char *cancel_type = argv[1];
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100856
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100857 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100858
859 subscr = gprs_subscr_get_by_imsi(imsi);
860 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100861 vty_out(vty, "%% no subscriber record for %s%s",
862 imsi, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100863 return CMD_WARNING;
864 }
865
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100866 if (strcmp(cancel_type, "update-procedure") == 0)
867 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
868 else
869 subscr->sgsn_data->error_cause = GMM_CAUSE_IMPL_DETACHED;
870
Jacob Erlbeck37139e52015-01-23 13:52:55 +0100871 gprs_subscr_cancel(subscr);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100872 gprs_subscr_put(subscr);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100873
874 return CMD_SUCCESS;
875}
876
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100877DEFUN(update_subscr_create, update_subscr_create_cmd,
878 UPDATE_SUBSCR_STR "create",
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100879 UPDATE_SUBSCR_HELP
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100880 "Create a subscriber entry\n")
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100881{
882 const char *imsi = argv[0];
883
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100884 struct gprs_subscr *subscr;
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100885
886 subscr = gprs_subscr_get_by_imsi(imsi);
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100887 if (subscr) {
888 vty_out(vty, "%% subscriber record already exists for %s%s",
889 imsi, VTY_NEWLINE);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100890 return CMD_WARNING;
891 }
892
Jacob Erlbeckd9193432015-01-19 14:11:46 +0100893 subscr = gprs_subscr_get_or_create(imsi);
894 subscr->keep_in_ram = 1;
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100895 gprs_subscr_put(subscr);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +0100896
897 return CMD_SUCCESS;
898}
899
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100900DEFUN(update_subscr_destroy, update_subscr_destroy_cmd,
901 UPDATE_SUBSCR_STR "destroy",
902 UPDATE_SUBSCR_HELP
903 "Destroy a subscriber entry\n")
904{
905 const char *imsi = argv[0];
906
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100907 struct gprs_subscr *subscr;
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100908
909 subscr = gprs_subscr_get_by_imsi(imsi);
910 if (!subscr) {
911 vty_out(vty, "%% subscriber record does not exist for %s%s",
912 imsi, VTY_NEWLINE);
913 return CMD_WARNING;
914 }
915
916 subscr->keep_in_ram = 0;
Jacob Erlbeck8000e0e2015-01-27 14:56:40 +0100917 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100918 gprs_subscr_cancel(subscr);
919 if (subscr->use_count > 1)
920 vty_out(vty, "%% subscriber is still in use%s",
921 VTY_NEWLINE);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100922 gprs_subscr_put(subscr);
Jacob Erlbecke988ae42015-01-27 12:41:19 +0100923
924 return CMD_SUCCESS;
925}
926
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100927#define UL_ERR_STR "system-failure|data-missing|unexpected-data-value|" \
928 "unknown-subscriber|roaming-not-allowed"
929
930#define UL_ERR_HELP \
931 "Force error code SystemFailure\n" \
932 "Force error code DataMissing\n" \
933 "Force error code UnexpectedDataValue\n" \
934 "Force error code UnknownSubscriber\n" \
935 "Force error code RoamingNotAllowed\n"
936
937DEFUN(update_subscr_update_location_result, update_subscr_update_location_result_cmd,
938 UPDATE_SUBSCR_STR "update-location-result (ok|" UL_ERR_STR ")",
939 UPDATE_SUBSCR_HELP
940 "Complete the update location procedure\n"
941 "The update location request succeeded\n"
942 UL_ERR_HELP)
943{
944 const char *imsi = argv[0];
945 const char *ret_code_str = argv[1];
946
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100947 struct gprs_subscr *subscr;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100948
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100949 const struct value_string cause_mapping[] = {
950 { GMM_CAUSE_NET_FAIL, "system-failure" },
951 { GMM_CAUSE_INV_MAND_INFO, "data-missing" },
952 { GMM_CAUSE_PROTO_ERR_UNSPEC, "unexpected-data-value" },
953 { GMM_CAUSE_IMSI_UNKNOWN, "unknown-subscriber" },
954 { GMM_CAUSE_GPRS_NOTALLOWED, "roaming-not-allowed" },
955 { 0, NULL }
956 };
957
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100958 subscr = gprs_subscr_get_by_imsi(imsi);
959 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100960 vty_out(vty, "%% unable to get subscriber record for %s%s",
961 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100962 return CMD_WARNING;
963 }
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100964
965 if (strcmp(ret_code_str, "ok") == 0) {
966 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100967 subscr->authorized = 1;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100968 } else {
969 subscr->sgsn_data->error_cause =
970 get_string_value(cause_mapping, ret_code_str);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100971 subscr->authorized = 0;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100972 }
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100973
974 gprs_subscr_update(subscr);
975
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100976 gprs_subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100977
978 return CMD_SUCCESS;
979}
980
981DEFUN(update_subscr_update_auth_info, update_subscr_update_auth_info_cmd,
982 UPDATE_SUBSCR_STR "update-auth-info",
983 UPDATE_SUBSCR_HELP
984 "Complete the send authentication info procedure\n")
985{
986 const char *imsi = argv[0];
987
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100988 struct gprs_subscr *subscr;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100989
990 subscr = gprs_subscr_get_by_imsi(imsi);
991 if (!subscr) {
Jacob Erlbeck15cc8c82015-01-19 14:29:43 +0100992 vty_out(vty, "%% unable to get subscriber record for %s%s",
993 imsi, VTY_NEWLINE);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100994 return CMD_WARNING;
995 }
996
997 gprs_subscr_update_auth_info(subscr);
998
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100999 gprs_subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001000
1001 return CMD_SUCCESS;
1002}
1003
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001004DEFUN(cfg_gsup_remote_ip, cfg_gsup_remote_ip_cmd,
1005 "gsup remote-ip A.B.C.D",
1006 "GSUP Parameters\n"
1007 "Set the IP address of the remote GSUP server\n"
1008 "IPv4 Address\n")
1009{
1010 inet_aton(argv[0], &g_cfg->gsup_server_addr.sin_addr);
1011
1012 return CMD_SUCCESS;
1013}
1014
1015DEFUN(cfg_gsup_remote_port, cfg_gsup_remote_port_cmd,
1016 "gsup remote-port <0-65535>",
1017 "GSUP Parameters\n"
1018 "Set the TCP port of the remote GSUP server\n"
1019 "Remote TCP port\n")
1020{
1021 g_cfg->gsup_server_port = atoi(argv[0]);
1022
1023 return CMD_SUCCESS;
1024}
1025
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001026DEFUN(cfg_gsup_oap_id, cfg_gsup_oap_id_cmd,
1027 "gsup oap-id <0-65535>",
1028 "GSUP Parameters\n"
1029 "Set the SGSN's OAP client ID\nOAP client ID (0 == disabled)\n")
1030{
1031 /* VTY ensures range */
1032 g_cfg->oap.client_id = (uint16_t)atoi(argv[0]);
1033 return CMD_SUCCESS;
1034}
1035
1036DEFUN(cfg_gsup_oap_k, cfg_gsup_oap_k_cmd,
1037 "gsup oap-k K",
1038 "GSUP Parameters\n"
1039 "Set the OAP shared secret K\nK value (16 byte) hex\n")
1040{
1041 const char *k = argv[0];
1042
1043 g_cfg->oap.secret_k_present = 0;
1044
1045 if ((!k) || (strlen(k) == 0))
1046 goto disable;
1047
1048 int k_len = osmo_hexparse(k,
1049 g_cfg->oap.secret_k,
1050 sizeof(g_cfg->oap.secret_k));
1051 if (k_len != 16) {
1052 vty_out(vty, "%% need exactly 16 octets for oap-k, got %d.%s",
1053 k_len, VTY_NEWLINE);
1054 goto disable;
1055 }
1056
1057 g_cfg->oap.secret_k_present = 1;
1058 return CMD_SUCCESS;
1059
1060disable:
1061 if (g_cfg->oap.client_id > 0) {
1062 vty_out(vty, "%% OAP client ID set, but invalid oap-k value disables OAP.%s",
1063 VTY_NEWLINE);
1064 return CMD_WARNING;
1065 }
1066 return CMD_SUCCESS;
1067}
1068
1069DEFUN(cfg_gsup_oap_opc, cfg_gsup_oap_opc_cmd,
1070 "gsup oap-opc OPC",
1071 "GSUP Parameters\n"
1072 "Set the OAP shared secret OPC\nOPC value (16 byte) hex\n")
1073{
1074 const char *opc = argv[0];
1075
1076 g_cfg->oap.secret_opc_present = 0;
1077
1078 if ((!opc) || (strlen(opc) == 0))
1079 goto disable;
1080
1081 int opc_len = osmo_hexparse(opc,
1082 g_cfg->oap.secret_opc,
1083 sizeof(g_cfg->oap.secret_opc));
1084 if (opc_len != 16) {
1085 vty_out(vty, "%% need exactly 16 octets for oap-opc, got %d.%s",
1086 opc_len, VTY_NEWLINE);
1087 goto disable;
1088 }
1089
1090 g_cfg->oap.secret_opc_present = 1;
1091 return CMD_SUCCESS;
1092
1093disable:
1094 if (g_cfg->oap.client_id > 0) {
1095 vty_out(vty, "%% OAP client ID set, but invalid oap-opc value disables OAP.%s",
1096 VTY_NEWLINE);
1097 return CMD_WARNING;
1098 }
1099 return CMD_SUCCESS;
1100}
1101
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001102DEFUN(cfg_apn_name, cfg_apn_name_cmd,
1103 "access-point-name NAME",
1104 "Configure a global list of allowed APNs\n"
1105 "Add this NAME to the list\n")
1106{
1107 return add_apn_ggsn_mapping(vty, argv[0], "", 0);
1108}
1109
1110DEFUN(cfg_no_apn_name, cfg_no_apn_name_cmd,
1111 "no access-point-name NAME",
1112 NO_STR "Configure a global list of allowed APNs\n"
1113 "Remove entry with NAME\n")
1114{
1115 struct apn_ctx *apn_ctx = sgsn_apn_ctx_by_name(argv[0], "");
1116 if (!apn_ctx)
1117 return CMD_SUCCESS;
1118
1119 sgsn_apn_ctx_free(apn_ctx);
1120 return CMD_SUCCESS;
1121}
1122
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001123DEFUN(cfg_cdr_filename, cfg_cdr_filename_cmd,
1124 "cdr filename NAME",
1125 "CDR\nSet filename\nname\n")
1126{
1127 talloc_free(g_cfg->cdr.filename);
1128 g_cfg->cdr.filename = talloc_strdup(tall_vty_ctx, argv[0]);
1129 return CMD_SUCCESS;
1130}
1131
1132DEFUN(cfg_no_cdr_filename, cfg_no_cdr_filename_cmd,
1133 "no cdr filename",
1134 NO_STR "CDR\nDisable CDR generation\n")
1135{
1136 talloc_free(g_cfg->cdr.filename);
1137 g_cfg->cdr.filename = NULL;
1138 return CMD_SUCCESS;
1139}
1140
1141DEFUN(cfg_cdr_interval, cfg_cdr_interval_cmd,
1142 "cdr interval <1-2147483647>",
1143 "CDR\nPDP periodic log interval\nSeconds\n")
1144{
1145 g_cfg->cdr.interval = atoi(argv[0]);
1146 return CMD_SUCCESS;
1147}
1148
Philippf1f34362016-08-26 17:00:21 +02001149#define COMPRESSION_STR "Configure compression\n"
1150DEFUN(cfg_no_comp_rfc1144, cfg_no_comp_rfc1144_cmd,
1151 "no compression rfc1144",
1152 NO_STR COMPRESSION_STR "disable rfc1144 TCP/IP header compression\n")
1153{
1154 g_cfg->pcomp_rfc1144.active = 0;
1155 g_cfg->pcomp_rfc1144.passive = 0;
1156 return CMD_SUCCESS;
1157}
1158
1159DEFUN(cfg_comp_rfc1144, cfg_comp_rfc1144_cmd,
1160 "compression rfc1144 active slots <1-256>",
1161 COMPRESSION_STR
1162 "RFC1144 Header compresion scheme\n"
1163 "Compression is actively proposed\n"
1164 "Number of compression state slots\n"
1165 "Number of compression state slots\n")
1166{
1167 g_cfg->pcomp_rfc1144.active = 1;
1168 g_cfg->pcomp_rfc1144.passive = 1;
1169 g_cfg->pcomp_rfc1144.s01 = atoi(argv[0]) - 1;
1170 return CMD_SUCCESS;
1171}
1172
1173DEFUN(cfg_comp_rfc1144p, cfg_comp_rfc1144p_cmd,
1174 "compression rfc1144 passive",
1175 COMPRESSION_STR
1176 "RFC1144 Header compresion scheme\n"
1177 "Compression is available on request\n")
1178{
1179 g_cfg->pcomp_rfc1144.active = 0;
1180 g_cfg->pcomp_rfc1144.passive = 1;
1181 return CMD_SUCCESS;
1182}
1183
Philipp73f83d52016-09-02 13:38:01 +02001184DEFUN(cfg_no_comp_v42bis, cfg_no_comp_v42bis_cmd,
1185 "no compression v42bis",
1186 NO_STR COMPRESSION_STR "disable V.42bis data compression\n")
1187{
1188 g_cfg->dcomp_v42bis.active = 0;
1189 g_cfg->dcomp_v42bis.passive = 0;
1190 return CMD_SUCCESS;
1191}
1192
1193DEFUN(cfg_comp_v42bis, cfg_comp_v42bis_cmd,
1194 "compression v42bis active direction (ms|sgsn|both) codewords <512-65535> strlen <6-250>",
1195 COMPRESSION_STR
1196 "V.42bis data compresion scheme\n"
1197 "Compression is actively proposed\n"
1198 "Direction in which the compression shall be active (p0)\n"
1199 "Compress ms->sgsn direction only\n"
1200 "Compress sgsn->ms direction only\n"
1201 "Both directions\n"
1202 "Number of codewords (p1)\n"
1203 "Number of codewords\n"
1204 "Maximum string length (p2)\n" "Maximum string length\n")
1205{
1206 g_cfg->dcomp_v42bis.active = 1;
1207 g_cfg->dcomp_v42bis.passive = 1;
1208
1209 switch (argv[0][0]) {
1210 case 'm':
1211 g_cfg->dcomp_v42bis.p0 = 1;
1212 break;
1213 case 's':
1214 g_cfg->dcomp_v42bis.p0 = 2;
1215 break;
1216 case 'b':
1217 g_cfg->dcomp_v42bis.p0 = 3;
1218 break;
1219 }
1220
1221 g_cfg->dcomp_v42bis.p1 = atoi(argv[1]);
1222 g_cfg->dcomp_v42bis.p2 = atoi(argv[2]);
1223 return CMD_SUCCESS;
1224}
1225
1226DEFUN(cfg_comp_v42bisp, cfg_comp_v42bisp_cmd,
1227 "compression v42bis passive",
1228 COMPRESSION_STR
1229 "V.42bis data compresion scheme\n"
1230 "Compression is available on request\n")
1231{
1232 g_cfg->dcomp_v42bis.active = 0;
1233 g_cfg->dcomp_v42bis.passive = 1;
1234 return CMD_SUCCESS;
1235}
1236
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001237int sgsn_vty_init(struct sgsn_config *cfg)
Harald Welte288be162010-05-01 16:48:27 +02001238{
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001239 g_cfg = cfg;
1240
Harald Welted193cb32010-05-17 22:58:03 +02001241 install_element_ve(&show_sgsn_cmd);
1242 //install_element_ve(&show_mmctx_tlli_cmd);
1243 install_element_ve(&show_mmctx_imsi_cmd);
1244 install_element_ve(&show_mmctx_all_cmd);
1245 install_element_ve(&show_pdpctx_all_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001246 install_element_ve(&show_subscr_cache_cmd);
1247
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01001248 install_element(ENABLE_NODE, &update_subscr_insert_auth_triplet_cmd);
Jacob Erlbeckd9193432015-01-19 14:11:46 +01001249 install_element(ENABLE_NODE, &update_subscr_create_cmd);
Jacob Erlbecke988ae42015-01-27 12:41:19 +01001250 install_element(ENABLE_NODE, &update_subscr_destroy_cmd);
Jacob Erlbeck207f4a52014-11-11 14:01:48 +01001251 install_element(ENABLE_NODE, &update_subscr_cancel_cmd);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001252 install_element(ENABLE_NODE, &update_subscr_update_location_result_cmd);
1253 install_element(ENABLE_NODE, &update_subscr_update_auth_info_cmd);
Harald Welte288be162010-05-01 16:48:27 +02001254
1255 install_element(CONFIG_NODE, &cfg_sgsn_cmd);
1256 install_node(&sgsn_node, config_write_sgsn);
Jacob Erlbeck36722e12013-10-29 09:30:30 +01001257 vty_install_default(SGSN_NODE);
Harald Weltee300d002010-06-02 12:41:34 +02001258 install_element(SGSN_NODE, &cfg_sgsn_bind_addr_cmd);
Harald Welted193cb32010-05-17 22:58:03 +02001259 install_element(SGSN_NODE, &cfg_ggsn_remote_ip_cmd);
1260 //install_element(SGSN_NODE, &cfg_ggsn_remote_port_cmd);
1261 install_element(SGSN_NODE, &cfg_ggsn_gtp_version_cmd);
Harald Welte7f6da482013-03-19 11:00:13 +01001262 install_element(SGSN_NODE, &cfg_imsi_acl_cmd);
Harald Welte3dfb5492013-03-19 11:48:54 +01001263 install_element(SGSN_NODE, &cfg_auth_policy_cmd);
Max93408ae2016-06-28 14:10:16 +02001264 install_element(SGSN_NODE, &cfg_encrypt_cmd);
Jacob Erlbeck39f040d2014-12-18 12:46:47 +01001265 install_element(SGSN_NODE, &cfg_gsup_remote_ip_cmd);
1266 install_element(SGSN_NODE, &cfg_gsup_remote_port_cmd);
Neels Hofmeyr568a7272015-10-12 11:57:38 +02001267 install_element(SGSN_NODE, &cfg_gsup_oap_id_cmd);
1268 install_element(SGSN_NODE, &cfg_gsup_oap_k_cmd);
1269 install_element(SGSN_NODE, &cfg_gsup_oap_opc_cmd);
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +01001270 install_element(SGSN_NODE, &cfg_apn_ggsn_cmd);
1271 install_element(SGSN_NODE, &cfg_apn_imsi_ggsn_cmd);
Holger Hans Peter Freyther9c20a5f2015-02-06 16:23:29 +01001272 install_element(SGSN_NODE, &cfg_apn_name_cmd);
1273 install_element(SGSN_NODE, &cfg_no_apn_name_cmd);
Holger Hans Peter Freytherc15c61c2015-05-06 17:46:08 +02001274 install_element(SGSN_NODE, &cfg_cdr_filename_cmd);
1275 install_element(SGSN_NODE, &cfg_no_cdr_filename_cmd);
1276 install_element(SGSN_NODE, &cfg_cdr_interval_cmd);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001277 install_element(SGSN_NODE, &cfg_ggsn_dynamic_lookup_cmd);
Holger Hans Peter Freythera5a6da42015-05-25 15:20:27 +08001278 install_element(SGSN_NODE, &cfg_grx_ggsn_cmd);
Harald Welte288be162010-05-01 16:48:27 +02001279
Harald Welte94508822015-08-15 19:08:21 +02001280 install_element(SGSN_NODE, &cfg_sgsn_T3312_cmd);
1281 install_element(SGSN_NODE, &cfg_sgsn_T3322_cmd);
1282 install_element(SGSN_NODE, &cfg_sgsn_T3350_cmd);
1283 install_element(SGSN_NODE, &cfg_sgsn_T3360_cmd);
1284 install_element(SGSN_NODE, &cfg_sgsn_T3370_cmd);
1285 install_element(SGSN_NODE, &cfg_sgsn_T3313_cmd);
1286 install_element(SGSN_NODE, &cfg_sgsn_T3314_cmd);
1287 install_element(SGSN_NODE, &cfg_sgsn_T3316_cmd);
1288 install_element(SGSN_NODE, &cfg_sgsn_T3385_cmd);
1289 install_element(SGSN_NODE, &cfg_sgsn_T3386_cmd);
1290 install_element(SGSN_NODE, &cfg_sgsn_T3395_cmd);
1291 install_element(SGSN_NODE, &cfg_sgsn_T3397_cmd);
1292
Philippf1f34362016-08-26 17:00:21 +02001293 install_element(SGSN_NODE, &cfg_no_comp_rfc1144_cmd);
1294 install_element(SGSN_NODE, &cfg_comp_rfc1144_cmd);
1295 install_element(SGSN_NODE, &cfg_comp_rfc1144p_cmd);
Philipp73f83d52016-09-02 13:38:01 +02001296 install_element(SGSN_NODE, &cfg_no_comp_v42bis_cmd);
1297 install_element(SGSN_NODE, &cfg_comp_v42bis_cmd);
1298 install_element(SGSN_NODE, &cfg_comp_v42bisp_cmd);
Neels Hofmeyr2188a772016-05-20 21:59:55 +02001299
1300#ifdef BUILD_IU
1301 iu_vty_init(SGSN_NODE, &g_cfg->iu.rab_assign_addr_enc);
1302#endif
Harald Welte288be162010-05-01 16:48:27 +02001303 return 0;
1304}
1305
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001306int sgsn_parse_config(const char *config_file)
Harald Welte288be162010-05-01 16:48:27 +02001307{
1308 int rc;
1309
Neels Hofmeyrc9a352f2017-07-20 14:41:20 +02001310 /* make sure sgsn_vty_init() was called before this */
1311 OSMO_ASSERT(g_cfg);
Harald Welte7f6da482013-03-19 11:00:13 +01001312
Harald Welte94508822015-08-15 19:08:21 +02001313 g_cfg->timers.T3312 = GSM0408_T3312_SECS;
1314 g_cfg->timers.T3322 = GSM0408_T3322_SECS;
1315 g_cfg->timers.T3350 = GSM0408_T3350_SECS;
1316 g_cfg->timers.T3360 = GSM0408_T3360_SECS;
1317 g_cfg->timers.T3370 = GSM0408_T3370_SECS;
1318 g_cfg->timers.T3313 = GSM0408_T3313_SECS;
1319 g_cfg->timers.T3314 = GSM0408_T3314_SECS;
1320 g_cfg->timers.T3316 = GSM0408_T3316_SECS;
1321 g_cfg->timers.T3385 = GSM0408_T3385_SECS;
1322 g_cfg->timers.T3386 = GSM0408_T3386_SECS;
1323 g_cfg->timers.T3395 = GSM0408_T3395_SECS;
1324 g_cfg->timers.T3397 = GSM0408_T3397_SECS;
1325
Harald Weltedcccb182010-05-16 20:52:23 +02001326 rc = vty_read_config_file(config_file, NULL);
Harald Welte288be162010-05-01 16:48:27 +02001327 if (rc < 0) {
1328 fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
1329 return rc;
1330 }
1331
Neels Hofmeyr27355c92017-02-24 06:28:31 +01001332 if (g_cfg->auth_policy == SGSN_AUTH_POLICY_REMOTE
1333 && !(g_cfg->gsup_server_addr.sin_addr.s_addr
1334 && g_cfg->gsup_server_port)) {
1335 fprintf(stderr, "Configuration error:"
1336 " 'auth-policy remote' requires both"
1337 " 'gsup remote-ip' and 'gsup remote-port'\n");
1338 return -EINVAL;
1339 }
1340
Harald Welte288be162010-05-01 16:48:27 +02001341 return 0;
1342}