blob: 21296ffed58293f579ed14505455523510216586 [file] [log] [blame]
Neels Hofmeyr183e7002017-10-06 02:59:54 +02001/* OsmoHLR subscriber management VTY implementation */
2/* (C) 2017 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
3 * All Rights Reserved
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU Affero General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Affero General Public License for more details.
14 *
15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <stdlib.h>
20#include <inttypes.h>
21#include <string.h>
22#include <errno.h>
Stefan Sperling5c14c9c2018-12-07 12:30:21 +010023#include <sys/types.h>
24#include <time.h>
Neels Hofmeyr183e7002017-10-06 02:59:54 +020025
26#include <osmocom/gsm/gsm23003.h>
27#include <osmocom/vty/vty.h>
28#include <osmocom/vty/command.h>
29#include <osmocom/core/utils.h>
Neels Hofmeyr7d29e342018-12-26 01:49:53 +010030#include <osmocom/gsm/gsm_utils.h>
Neels Hofmeyr183e7002017-10-06 02:59:54 +020031
32#include "hlr.h"
33#include "db.h"
34
35struct vty;
36
37#define hexdump_buf(buf) osmo_hexdump_nospc((void*)buf, sizeof(buf))
38
Neels Hofmeyr18a1b012018-12-25 17:23:41 +010039static char *get_datestr(const time_t *t)
Stefan Sperling5c14c9c2018-12-07 12:30:21 +010040{
Neels Hofmeyr18a1b012018-12-25 17:23:41 +010041 static char buf[32];
42 struct tm tm;
Stefan Sperling5c14c9c2018-12-07 12:30:21 +010043
Neels Hofmeyr18a1b012018-12-25 17:23:41 +010044 tm = *gmtime(t);
45
46 strftime(buf, sizeof(buf), "%FT%T+00:00", &tm);
47 return buf;
Stefan Sperling5c14c9c2018-12-07 12:30:21 +010048}
49
Neels Hofmeyr183e7002017-10-06 02:59:54 +020050static void subscr_dump_full_vty(struct vty *vty, struct hlr_subscriber *subscr)
51{
52 int rc;
Neels Hofmeyr7d29e342018-12-26 01:49:53 +010053 int i;
Neels Hofmeyr183e7002017-10-06 02:59:54 +020054 struct osmo_sub_auth_data aud2g;
55 struct osmo_sub_auth_data aud3g;
56
57 vty_out(vty, " ID: %"PRIu64"%s", subscr->id, VTY_NEWLINE);
58
Neels Hofmeyr36bec872017-10-23 18:44:23 +020059 vty_out(vty, " IMSI: %s%s", *subscr->imsi ? subscr->imsi : "none", VTY_NEWLINE);
Neels Hofmeyr183e7002017-10-06 02:59:54 +020060 vty_out(vty, " MSISDN: %s%s", *subscr->msisdn ? subscr->msisdn : "none", VTY_NEWLINE);
61 if (*subscr->vlr_number)
62 vty_out(vty, " VLR number: %s%s", subscr->vlr_number, VTY_NEWLINE);
63 if (*subscr->sgsn_number)
64 vty_out(vty, " SGSN number: %s%s", subscr->sgsn_number, VTY_NEWLINE);
65 if (*subscr->sgsn_address)
66 vty_out(vty, " SGSN address: %s%s", subscr->sgsn_address, VTY_NEWLINE);
67 if (subscr->periodic_lu_timer)
68 vty_out(vty, " Periodic LU timer: %u%s", subscr->periodic_lu_timer, VTY_NEWLINE);
69 if (subscr->periodic_rau_tau_timer)
70 vty_out(vty, " Periodic RAU/TAU timer: %u%s", subscr->periodic_rau_tau_timer, VTY_NEWLINE);
71 if (subscr->lmsi)
72 vty_out(vty, " LMSI: %x%s", subscr->lmsi, VTY_NEWLINE);
73 if (!subscr->nam_cs)
74 vty_out(vty, " CS disabled%s", VTY_NEWLINE);
75 if (subscr->ms_purged_cs)
76 vty_out(vty, " CS purged%s", VTY_NEWLINE);
77 if (!subscr->nam_ps)
78 vty_out(vty, " PS disabled%s", VTY_NEWLINE);
79 if (subscr->ms_purged_ps)
80 vty_out(vty, " PS purged%s", VTY_NEWLINE);
Stefan Sperling5c14c9c2018-12-07 12:30:21 +010081 if (subscr->last_lu_seen)
Neels Hofmeyr18a1b012018-12-25 17:23:41 +010082 vty_out(vty, " last LU seen: %s%s", get_datestr(&subscr->last_lu_seen), VTY_NEWLINE);
Neels Hofmeyr7d29e342018-12-26 01:49:53 +010083 for (i = OSMO_RAT_UNKNOWN + 1; i < ARRAY_SIZE(subscr->rat_types); i++) {
84 vty_out(vty, " %s: %s%s", osmo_rat_type_name(i), subscr->rat_types[i] ? "allowed" : "forbidden",
85 VTY_NEWLINE);
86 }
87 if (subscr->ms_purged_cs)
88 vty_out(vty, " CS purged%s", VTY_NEWLINE);
Neels Hofmeyr183e7002017-10-06 02:59:54 +020089
90 if (!*subscr->imsi)
91 return;
92
93 OSMO_ASSERT(g_hlr);
94 rc = db_get_auth_data(g_hlr->dbc, subscr->imsi, &aud2g, &aud3g, NULL);
95
Neels Hofmeyrbd1dca02017-11-23 15:25:30 +010096 switch (rc) {
97 case 0:
98 break;
99 case -ENOENT:
100 case -ENOKEY:
101 aud2g.algo = OSMO_AUTH_ALG_NONE;
102 aud3g.algo = OSMO_AUTH_ALG_NONE;
103 break;
104 default:
105 vty_out(vty, "%% Error retrieving data from database (%d)%s", rc, VTY_NEWLINE);
106 return;
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200107 }
108
109 if (aud2g.type != OSMO_AUTH_TYPE_NONE && aud2g.type != OSMO_AUTH_TYPE_GSM) {
110 vty_out(vty, "%% Error: 2G auth data is not of type 'GSM'%s", VTY_NEWLINE);
111 aud2g = (struct osmo_sub_auth_data){};
112 }
113
114 if (aud3g.type != OSMO_AUTH_TYPE_NONE && aud3g.type != OSMO_AUTH_TYPE_UMTS) {
115 vty_out(vty, "%% Error: 3G auth data is not of type 'UMTS'%s", VTY_NEWLINE);
116 aud3g = (struct osmo_sub_auth_data){};
117 }
118
119 if (aud2g.algo != OSMO_AUTH_ALG_NONE && aud2g.type != OSMO_AUTH_TYPE_NONE) {
120 vty_out(vty, " 2G auth: %s%s",
121 osmo_auth_alg_name(aud2g.algo), VTY_NEWLINE);
122 vty_out(vty, " KI=%s%s",
123 hexdump_buf(aud2g.u.gsm.ki), VTY_NEWLINE);
124 }
125
126 if (aud3g.algo != OSMO_AUTH_ALG_NONE && aud3g.type != OSMO_AUTH_TYPE_NONE) {
127 vty_out(vty, " 3G auth: %s%s", osmo_auth_alg_name(aud3g.algo), VTY_NEWLINE);
128 vty_out(vty, " K=%s%s", hexdump_buf(aud3g.u.umts.k), VTY_NEWLINE);
129 vty_out(vty, " %s=%s%s", aud3g.u.umts.opc_is_op? "OP" : "OPC",
130 hexdump_buf(aud3g.u.umts.opc), VTY_NEWLINE);
131 vty_out(vty, " IND-bitlen=%u", aud3g.u.umts.ind_bitlen);
132 if (aud3g.u.umts.sqn)
133 vty_out(vty, " last-SQN=%"PRIu64, aud3g.u.umts.sqn);
134 vty_out(vty, VTY_NEWLINE);
135 }
136}
137
138static int get_subscr_by_argv(struct vty *vty, const char *type, const char *id, struct hlr_subscriber *subscr)
139{
140 int rc = -1;
141 if (strcmp(type, "imsi") == 0)
142 rc = db_subscr_get_by_imsi(g_hlr->dbc, id, subscr);
143 else if (strcmp(type, "msisdn") == 0)
144 rc = db_subscr_get_by_msisdn(g_hlr->dbc, id, subscr);
145 else if (strcmp(type, "id") == 0)
146 rc = db_subscr_get_by_id(g_hlr->dbc, atoll(id), subscr);
147 if (rc)
148 vty_out(vty, "%% No subscriber for %s = '%s'%s",
149 type, id, VTY_NEWLINE);
150 return rc;
151}
152
153#define SUBSCR_CMD "subscriber "
154#define SUBSCR_CMD_HELP "Subscriber management commands\n"
155
Neels Hofmeyr8aa780b2018-12-02 18:52:49 +0100156#define SUBSCR_ID "(imsi|msisdn|id) IDENT"
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200157#define SUBSCR_ID_HELP \
158 "Identify subscriber by IMSI\n" \
159 "Identify subscriber by MSISDN (phone number)\n" \
160 "Identify subscriber by database ID\n" \
161 "IMSI/MSISDN/ID of the subscriber\n"
162
Neels Hofmeyr8aa780b2018-12-02 18:52:49 +0100163#define SUBSCR SUBSCR_CMD SUBSCR_ID " "
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200164#define SUBSCR_HELP SUBSCR_CMD_HELP SUBSCR_ID_HELP
165
166#define SUBSCR_UPDATE SUBSCR "update "
167#define SUBSCR_UPDATE_HELP SUBSCR_HELP "Set or update subscriber data\n"
Neels Hofmeyra820ea12018-12-02 19:46:46 +0100168#define SUBSCR_MSISDN_HELP "Set MSISDN (phone number) of the subscriber\n"
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200169
170DEFUN(subscriber_show,
171 subscriber_show_cmd,
172 SUBSCR "show",
173 SUBSCR_HELP "Show subscriber information\n")
174{
175 struct hlr_subscriber subscr;
176 const char *id_type = argv[0];
177 const char *id = argv[1];
178
179 if (get_subscr_by_argv(vty, id_type, id, &subscr))
180 return CMD_WARNING;
181
182 subscr_dump_full_vty(vty, &subscr);
183 return CMD_SUCCESS;
184}
185
Neels Hofmeyr8aa780b2018-12-02 18:52:49 +0100186ALIAS(subscriber_show, show_subscriber_cmd,
187 "show " SUBSCR_CMD SUBSCR_ID,
188 SHOW_STR SUBSCR_CMD_HELP SUBSCR_ID_HELP);
189
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200190DEFUN(subscriber_create,
191 subscriber_create_cmd,
192 SUBSCR_CMD "imsi IDENT create",
193 SUBSCR_CMD_HELP
Vadim Yanitskiyf473c7b2018-07-30 14:29:39 +0700194 "Identify subscriber by IMSI\n"
195 "IMSI/MSISDN/ID of the subscriber\n"
196 "Create subscriber by IMSI\n")
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200197{
198 int rc;
199 struct hlr_subscriber subscr;
200 const char *imsi = argv[0];
201
202 if (!osmo_imsi_str_valid(imsi)) {
203 vty_out(vty, "%% Not a valid IMSI: %s%s", imsi, VTY_NEWLINE);
204 return CMD_WARNING;
205 }
206
207 rc = db_subscr_create(g_hlr->dbc, imsi);
208
209 if (rc) {
210 if (rc == -EEXIST)
211 vty_out(vty, "%% Subscriber already exists for IMSI = %s%s",
212 imsi, VTY_NEWLINE);
213 else
214 vty_out(vty, "%% Error (rc=%d): cannot create subscriber for IMSI = %s%s",
215 rc, imsi, VTY_NEWLINE);
216 return CMD_WARNING;
217 }
218
219 rc = db_subscr_get_by_imsi(g_hlr->dbc, imsi, &subscr);
220 vty_out(vty, "%% Created subscriber %s%s", imsi, VTY_NEWLINE);
221
222 subscr_dump_full_vty(vty, &subscr);
223
224 return CMD_SUCCESS;
225}
226
227DEFUN(subscriber_delete,
228 subscriber_delete_cmd,
229 SUBSCR "delete",
230 SUBSCR_HELP "Delete subscriber from database\n")
231{
232 struct hlr_subscriber subscr;
233 int rc;
234 const char *id_type = argv[0];
235 const char *id = argv[1];
236
237 /* Find out the IMSI regardless of which way the caller decided to
238 * identify the subscriber by. */
239 if (get_subscr_by_argv(vty, id_type, id, &subscr))
240 return CMD_WARNING;
241
242 rc = db_subscr_delete_by_id(g_hlr->dbc, subscr.id);
243 if (rc) {
244 vty_out(vty, "%% Error: Failed to remove subscriber for IMSI '%s'%s",
245 subscr.imsi, VTY_NEWLINE);
246 return CMD_WARNING;
247 }
248
249 vty_out(vty, "%% Deleted subscriber for IMSI '%s'%s", subscr.imsi, VTY_NEWLINE);
250 return CMD_SUCCESS;
251}
252
253DEFUN(subscriber_msisdn,
254 subscriber_msisdn_cmd,
Neels Hofmeyra820ea12018-12-02 19:46:46 +0100255 SUBSCR_UPDATE "msisdn (none|MSISDN)",
256 SUBSCR_UPDATE_HELP SUBSCR_MSISDN_HELP
257 "Remove MSISDN (phone number)\n"
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200258 "New MSISDN (phone number)\n")
259{
260 struct hlr_subscriber subscr;
261 const char *id_type = argv[0];
262 const char *id = argv[1];
263 const char *msisdn = argv[2];
264
Neels Hofmeyra820ea12018-12-02 19:46:46 +0100265 if (strcmp(msisdn, "none") == 0)
266 msisdn = NULL;
267 else {
268 if (strlen(msisdn) > sizeof(subscr.msisdn) - 1) {
269 vty_out(vty, "%% MSISDN is too long, max. %zu characters are allowed%s",
270 sizeof(subscr.msisdn)-1, VTY_NEWLINE);
271 return CMD_WARNING;
272 }
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200273
Neels Hofmeyra820ea12018-12-02 19:46:46 +0100274 if (!osmo_msisdn_str_valid(msisdn)) {
275 vty_out(vty, "%% MSISDN invalid: '%s'%s", msisdn, VTY_NEWLINE);
276 return CMD_WARNING;
277 }
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200278 }
279
280 if (get_subscr_by_argv(vty, id_type, id, &subscr))
281 return CMD_WARNING;
282
283 if (db_subscr_update_msisdn_by_imsi(g_hlr->dbc, subscr.imsi, msisdn)) {
284 vty_out(vty, "%% Error: cannot update MSISDN for subscriber IMSI='%s'%s",
285 subscr.imsi, VTY_NEWLINE);
286 return CMD_WARNING;
287 }
288
Neels Hofmeyra820ea12018-12-02 19:46:46 +0100289 if (msisdn) {
290 vty_out(vty, "%% Updated subscriber IMSI='%s' to MSISDN='%s'%s",
291 subscr.imsi, msisdn, VTY_NEWLINE);
Stefan Sperlingf1622522018-04-09 11:39:16 +0200292
Neels Hofmeyra820ea12018-12-02 19:46:46 +0100293 if (db_subscr_get_by_msisdn(g_hlr->dbc, msisdn, &subscr) == 0)
294 osmo_hlr_subscriber_update_notify(&subscr);
295 } else {
296 vty_out(vty, "%% Updated subscriber IMSI='%s': removed MSISDN%s",
297 subscr.imsi, VTY_NEWLINE);
298
Stefan Sperlingf1622522018-04-09 11:39:16 +0200299 osmo_hlr_subscriber_update_notify(&subscr);
Neels Hofmeyra820ea12018-12-02 19:46:46 +0100300 }
Stefan Sperlingf1622522018-04-09 11:39:16 +0200301
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200302 return CMD_SUCCESS;
303}
304
305static bool is_hexkey_valid(struct vty *vty, const char *label,
306 const char *hex_str, int minlen, int maxlen)
307{
308 if (osmo_is_hexstr(hex_str, minlen * 2, maxlen * 2, true))
309 return true;
310 vty_out(vty, "%% Invalid value for %s: '%s'%s", label, hex_str, VTY_NEWLINE);
311 return false;
312}
313
314#define AUTH_ALG_TYPES_2G "(comp128v1|comp128v2|comp128v3|xor)"
315#define AUTH_ALG_TYPES_2G_HELP \
316 "Use COMP128v1 algorithm\n" \
317 "Use COMP128v2 algorithm\n" \
318 "Use COMP128v3 algorithm\n" \
319 "Use XOR algorithm\n"
320
321#define AUTH_ALG_TYPES_3G "milenage"
322#define AUTH_ALG_TYPES_3G_HELP \
323 "Use Milenage algorithm\n"
324
325#define A38_XOR_MIN_KEY_LEN 12
326#define A38_XOR_MAX_KEY_LEN 16
327#define A38_COMP128_KEY_LEN 16
328
329#define MILENAGE_KEY_LEN 16
330
331static bool auth_algo_parse(const char *alg_str, enum osmo_auth_algo *algo,
332 int *minlen, int *maxlen)
333{
334 if (!strcasecmp(alg_str, "none")) {
335 *algo = OSMO_AUTH_ALG_NONE;
336 *minlen = *maxlen = 0;
337 } else if (!strcasecmp(alg_str, "comp128v1")) {
338 *algo = OSMO_AUTH_ALG_COMP128v1;
339 *minlen = *maxlen = A38_COMP128_KEY_LEN;
340 } else if (!strcasecmp(alg_str, "comp128v2")) {
341 *algo = OSMO_AUTH_ALG_COMP128v2;
342 *minlen = *maxlen = A38_COMP128_KEY_LEN;
343 } else if (!strcasecmp(alg_str, "comp128v3")) {
344 *algo = OSMO_AUTH_ALG_COMP128v3;
345 *minlen = *maxlen = A38_COMP128_KEY_LEN;
346 } else if (!strcasecmp(alg_str, "xor")) {
347 *algo = OSMO_AUTH_ALG_XOR;
348 *minlen = A38_XOR_MIN_KEY_LEN;
349 *maxlen = A38_XOR_MAX_KEY_LEN;
350 } else if (!strcasecmp(alg_str, "milenage")) {
351 *algo = OSMO_AUTH_ALG_MILENAGE;
352 *minlen = *maxlen = MILENAGE_KEY_LEN;
353 } else
354 return false;
355 return true;
356}
357
358DEFUN(subscriber_no_aud2g,
359 subscriber_no_aud2g_cmd,
360 SUBSCR_UPDATE "aud2g none",
361 SUBSCR_UPDATE_HELP
362 "Set 2G authentication data\n"
363 "Delete 2G authentication data\n")
364{
365 struct hlr_subscriber subscr;
366 int rc;
367 const char *id_type = argv[0];
368 const char *id = argv[1];
369 struct sub_auth_data_str aud = {
370 .type = OSMO_AUTH_TYPE_GSM,
371 .algo = OSMO_AUTH_ALG_NONE,
372 };
373
374 if (get_subscr_by_argv(vty, id_type, id, &subscr))
375 return CMD_WARNING;
376
377 rc = db_subscr_update_aud_by_id(g_hlr->dbc, subscr.id, &aud);
378
Harald Welte880a34d2018-03-01 21:32:01 +0100379 if (rc && rc != -ENOENT) {
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200380 vty_out(vty, "%% Error: cannot disable 2G auth data for IMSI='%s'%s",
381 subscr.imsi, VTY_NEWLINE);
382 return CMD_WARNING;
383 }
384 return CMD_SUCCESS;
385}
386
387DEFUN(subscriber_aud2g,
388 subscriber_aud2g_cmd,
389 SUBSCR_UPDATE "aud2g " AUTH_ALG_TYPES_2G " ki KI",
390 SUBSCR_UPDATE_HELP
391 "Set 2G authentication data\n"
392 AUTH_ALG_TYPES_2G_HELP
393 "Set Ki Encryption Key\n" "Ki as 32 hexadecimal characters\n")
394{
395 struct hlr_subscriber subscr;
396 int rc;
397 int minlen = 0;
398 int maxlen = 0;
399 const char *id_type = argv[0];
400 const char *id = argv[1];
401 const char *alg_type = argv[2];
402 const char *ki = argv[3];
403 struct sub_auth_data_str aud2g = {
404 .type = OSMO_AUTH_TYPE_GSM,
405 .u.gsm.ki = ki,
406 };
407
408 if (!auth_algo_parse(alg_type, &aud2g.algo, &minlen, &maxlen)) {
409 vty_out(vty, "%% Unknown auth algorithm: '%s'%s", alg_type, VTY_NEWLINE);
410 return CMD_WARNING;
411 }
412
413 if (!is_hexkey_valid(vty, "KI", aud2g.u.gsm.ki, minlen, maxlen))
414 return CMD_WARNING;
415
416 if (get_subscr_by_argv(vty, id_type, id, &subscr))
417 return CMD_WARNING;
418
419 rc = db_subscr_update_aud_by_id(g_hlr->dbc, subscr.id, &aud2g);
420
421 if (rc) {
422 vty_out(vty, "%% Error: cannot set 2G auth data for IMSI='%s'%s",
423 subscr.imsi, VTY_NEWLINE);
424 return CMD_WARNING;
425 }
426 return CMD_SUCCESS;
427}
428
429DEFUN(subscriber_no_aud3g,
430 subscriber_no_aud3g_cmd,
431 SUBSCR_UPDATE "aud3g none",
432 SUBSCR_UPDATE_HELP
433 "Set UMTS authentication data (3G, and 2G with UMTS AKA)\n"
434 "Delete 3G authentication data\n")
435{
436 struct hlr_subscriber subscr;
437 int rc;
438 const char *id_type = argv[0];
439 const char *id = argv[1];
440 struct sub_auth_data_str aud = {
441 .type = OSMO_AUTH_TYPE_UMTS,
442 .algo = OSMO_AUTH_ALG_NONE,
443 };
444
445 if (get_subscr_by_argv(vty, id_type, id, &subscr))
446 return CMD_WARNING;
447
448 rc = db_subscr_update_aud_by_id(g_hlr->dbc, subscr.id, &aud);
449
Harald Welte880a34d2018-03-01 21:32:01 +0100450 if (rc && rc != -ENOENT) {
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200451 vty_out(vty, "%% Error: cannot disable 3G auth data for IMSI='%s'%s",
452 subscr.imsi, VTY_NEWLINE);
453 return CMD_WARNING;
454 }
455 return CMD_SUCCESS;
456}
457
458DEFUN(subscriber_aud3g,
459 subscriber_aud3g_cmd,
460 SUBSCR_UPDATE "aud3g " AUTH_ALG_TYPES_3G
461 " k K"
462 " (op|opc) OP_C"
463 " [ind-bitlen] [<0-28>]",
464 SUBSCR_UPDATE_HELP
465 "Set UMTS authentication data (3G, and 2G with UMTS AKA)\n"
466 AUTH_ALG_TYPES_3G_HELP
467 "Set Encryption Key K\n" "K as 32 hexadecimal characters\n"
468 "Set OP key\n" "Set OPC key\n" "OP or OPC as 32 hexadecimal characters\n"
469 "Set IND bit length\n" "IND bit length value (default: 5)\n")
470{
471 struct hlr_subscriber subscr;
472 int minlen = 0;
473 int maxlen = 0;
474 int rc;
475 const char *id_type = argv[0];
476 const char *id = argv[1];
477 const char *alg_type = AUTH_ALG_TYPES_3G;
478 const char *k = argv[2];
479 bool opc_is_op = (strcasecmp("op", argv[3]) == 0);
480 const char *op_opc = argv[4];
481 int ind_bitlen = argc > 6? atoi(argv[6]) : 5;
482 struct sub_auth_data_str aud3g = {
483 .type = OSMO_AUTH_TYPE_UMTS,
484 .u.umts = {
485 .k = k,
486 .opc_is_op = opc_is_op,
487 .opc = op_opc,
488 .ind_bitlen = ind_bitlen,
489 },
490 };
491
492 if (!auth_algo_parse(alg_type, &aud3g.algo, &minlen, &maxlen)) {
493 vty_out(vty, "%% Unknown auth algorithm: '%s'%s", alg_type, VTY_NEWLINE);
494 return CMD_WARNING;
495 }
496
497 if (!is_hexkey_valid(vty, "K", aud3g.u.umts.k, minlen, maxlen))
498 return CMD_WARNING;
499
500 if (!is_hexkey_valid(vty, opc_is_op ? "OP" : "OPC", aud3g.u.umts.opc,
501 MILENAGE_KEY_LEN, MILENAGE_KEY_LEN))
502 return CMD_WARNING;
503
504 if (get_subscr_by_argv(vty, id_type, id, &subscr))
505 return CMD_WARNING;
506
507 rc = db_subscr_update_aud_by_id(g_hlr->dbc, subscr.id, &aud3g);
508
509 if (rc) {
510 vty_out(vty, "%% Error: cannot set 3G auth data for IMSI='%s'%s",
511 subscr.imsi, VTY_NEWLINE);
512 return CMD_WARNING;
513 }
514 return CMD_SUCCESS;
515}
516
Neels Hofmeyr7d29e342018-12-26 01:49:53 +0100517DEFUN(subscriber_rat,
518 subscriber_rat_cmd,
519 SUBSCR_UPDATE "rat (geran-a|utran-iu) (allowed|forbidden)",
520 SUBSCR_UPDATE_HELP
521 "Allow or forbid specific Radio Access Types\n"
522 "Set access to GERAN-A\n"
523 "Set access to UTRAN-Iu\n"
524 "Allow access\n"
525 "Forbid access\n")
526{
527 struct hlr_subscriber subscr;
528 const char *id_type = argv[0];
529 const char *id = argv[1];
530 const char *rat_str = argv[2];
531 const char *allowed_forbidden = argv[3];
532 enum osmo_rat_type rat;
533 bool allowed;
534 int rc;
535
536 if (strcmp(rat_str, "geran-a") == 0)
537 rat = OSMO_RAT_GERAN_A;
538 else if (strcmp(rat_str, "utran-iu") == 0)
539 rat = OSMO_RAT_UTRAN_IU;
540
541 allowed = (strcmp(allowed_forbidden, "allowed") == 0);
542
543 if (get_subscr_by_argv(vty, id_type, id, &subscr))
544 return CMD_WARNING;
545
546 rc = hlr_subscr_rat_flag(g_hlr, &subscr, rat, allowed);
547
548 if (rc && rc != -ENOEXEC) {
549 vty_out(vty, "%% Error: cannot set %s to %s%s",
550 osmo_rat_type_name(rat), allowed ? "allowed" : "forbidden", VTY_NEWLINE);
551 return CMD_WARNING;
552 }
553 return CMD_SUCCESS;
554}
555
Harald Welted5807b82018-07-29 12:27:41 +0200556void hlr_vty_subscriber_init(void)
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200557{
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200558 install_element_ve(&subscriber_show_cmd);
Neels Hofmeyr8aa780b2018-12-02 18:52:49 +0100559 install_element_ve(&show_subscriber_cmd);
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200560 install_element(ENABLE_NODE, &subscriber_create_cmd);
561 install_element(ENABLE_NODE, &subscriber_delete_cmd);
562 install_element(ENABLE_NODE, &subscriber_msisdn_cmd);
563 install_element(ENABLE_NODE, &subscriber_no_aud2g_cmd);
564 install_element(ENABLE_NODE, &subscriber_aud2g_cmd);
565 install_element(ENABLE_NODE, &subscriber_no_aud3g_cmd);
566 install_element(ENABLE_NODE, &subscriber_aud3g_cmd);
Neels Hofmeyr7d29e342018-12-26 01:49:53 +0100567 install_element(ENABLE_NODE, &subscriber_rat_cmd);
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200568}