blob: 92cfa2a3c3ae7d3b15c522c23c8679358f83fc4f [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>
30
31#include "hlr.h"
32#include "db.h"
33
34struct vty;
35
36#define hexdump_buf(buf) osmo_hexdump_nospc((void*)buf, sizeof(buf))
37
Stefan Sperling5c14c9c2018-12-07 12:30:21 +010038static char *
39get_datestr(const time_t *t, char *datebuf)
40{
41 char *p, *s = ctime_r(t, datebuf);
42
43 /* Strip trailing newline. */
44 p = strchr(s, '\n');
45 if (p)
46 *p = '\0';
47 return s;
48}
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;
53 struct osmo_sub_auth_data aud2g;
54 struct osmo_sub_auth_data aud3g;
Stefan Sperling5c14c9c2018-12-07 12:30:21 +010055 char datebuf[26]; /* for ctime_r(3) */
Neels Hofmeyr183e7002017-10-06 02:59:54 +020056
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)
82 vty_out(vty, " last LU seen: %s UTC%s", get_datestr(&subscr->last_lu_seen, datebuf), VTY_NEWLINE);
Neels Hofmeyr183e7002017-10-06 02:59:54 +020083
84 if (!*subscr->imsi)
85 return;
86
87 OSMO_ASSERT(g_hlr);
88 rc = db_get_auth_data(g_hlr->dbc, subscr->imsi, &aud2g, &aud3g, NULL);
89
Neels Hofmeyrbd1dca02017-11-23 15:25:30 +010090 switch (rc) {
91 case 0:
92 break;
93 case -ENOENT:
94 case -ENOKEY:
95 aud2g.algo = OSMO_AUTH_ALG_NONE;
96 aud3g.algo = OSMO_AUTH_ALG_NONE;
97 break;
98 default:
99 vty_out(vty, "%% Error retrieving data from database (%d)%s", rc, VTY_NEWLINE);
100 return;
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200101 }
102
103 if (aud2g.type != OSMO_AUTH_TYPE_NONE && aud2g.type != OSMO_AUTH_TYPE_GSM) {
104 vty_out(vty, "%% Error: 2G auth data is not of type 'GSM'%s", VTY_NEWLINE);
105 aud2g = (struct osmo_sub_auth_data){};
106 }
107
108 if (aud3g.type != OSMO_AUTH_TYPE_NONE && aud3g.type != OSMO_AUTH_TYPE_UMTS) {
109 vty_out(vty, "%% Error: 3G auth data is not of type 'UMTS'%s", VTY_NEWLINE);
110 aud3g = (struct osmo_sub_auth_data){};
111 }
112
113 if (aud2g.algo != OSMO_AUTH_ALG_NONE && aud2g.type != OSMO_AUTH_TYPE_NONE) {
114 vty_out(vty, " 2G auth: %s%s",
115 osmo_auth_alg_name(aud2g.algo), VTY_NEWLINE);
116 vty_out(vty, " KI=%s%s",
117 hexdump_buf(aud2g.u.gsm.ki), VTY_NEWLINE);
118 }
119
120 if (aud3g.algo != OSMO_AUTH_ALG_NONE && aud3g.type != OSMO_AUTH_TYPE_NONE) {
121 vty_out(vty, " 3G auth: %s%s", osmo_auth_alg_name(aud3g.algo), VTY_NEWLINE);
122 vty_out(vty, " K=%s%s", hexdump_buf(aud3g.u.umts.k), VTY_NEWLINE);
123 vty_out(vty, " %s=%s%s", aud3g.u.umts.opc_is_op? "OP" : "OPC",
124 hexdump_buf(aud3g.u.umts.opc), VTY_NEWLINE);
125 vty_out(vty, " IND-bitlen=%u", aud3g.u.umts.ind_bitlen);
126 if (aud3g.u.umts.sqn)
127 vty_out(vty, " last-SQN=%"PRIu64, aud3g.u.umts.sqn);
128 vty_out(vty, VTY_NEWLINE);
129 }
130}
131
132static int get_subscr_by_argv(struct vty *vty, const char *type, const char *id, struct hlr_subscriber *subscr)
133{
134 int rc = -1;
135 if (strcmp(type, "imsi") == 0)
136 rc = db_subscr_get_by_imsi(g_hlr->dbc, id, subscr);
137 else if (strcmp(type, "msisdn") == 0)
138 rc = db_subscr_get_by_msisdn(g_hlr->dbc, id, subscr);
139 else if (strcmp(type, "id") == 0)
140 rc = db_subscr_get_by_id(g_hlr->dbc, atoll(id), subscr);
141 if (rc)
142 vty_out(vty, "%% No subscriber for %s = '%s'%s",
143 type, id, VTY_NEWLINE);
144 return rc;
145}
146
147#define SUBSCR_CMD "subscriber "
148#define SUBSCR_CMD_HELP "Subscriber management commands\n"
149
Neels Hofmeyr8aa780b2018-12-02 18:52:49 +0100150#define SUBSCR_ID "(imsi|msisdn|id) IDENT"
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200151#define SUBSCR_ID_HELP \
152 "Identify subscriber by IMSI\n" \
153 "Identify subscriber by MSISDN (phone number)\n" \
154 "Identify subscriber by database ID\n" \
155 "IMSI/MSISDN/ID of the subscriber\n"
156
Neels Hofmeyr8aa780b2018-12-02 18:52:49 +0100157#define SUBSCR SUBSCR_CMD SUBSCR_ID " "
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200158#define SUBSCR_HELP SUBSCR_CMD_HELP SUBSCR_ID_HELP
159
160#define SUBSCR_UPDATE SUBSCR "update "
161#define SUBSCR_UPDATE_HELP SUBSCR_HELP "Set or update subscriber data\n"
Neels Hofmeyra820ea12018-12-02 19:46:46 +0100162#define SUBSCR_MSISDN_HELP "Set MSISDN (phone number) of the subscriber\n"
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200163
164DEFUN(subscriber_show,
165 subscriber_show_cmd,
166 SUBSCR "show",
167 SUBSCR_HELP "Show subscriber information\n")
168{
169 struct hlr_subscriber subscr;
170 const char *id_type = argv[0];
171 const char *id = argv[1];
172
173 if (get_subscr_by_argv(vty, id_type, id, &subscr))
174 return CMD_WARNING;
175
176 subscr_dump_full_vty(vty, &subscr);
177 return CMD_SUCCESS;
178}
179
Neels Hofmeyr8aa780b2018-12-02 18:52:49 +0100180ALIAS(subscriber_show, show_subscriber_cmd,
181 "show " SUBSCR_CMD SUBSCR_ID,
182 SHOW_STR SUBSCR_CMD_HELP SUBSCR_ID_HELP);
183
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200184DEFUN(subscriber_create,
185 subscriber_create_cmd,
186 SUBSCR_CMD "imsi IDENT create",
187 SUBSCR_CMD_HELP
Vadim Yanitskiyf473c7b2018-07-30 14:29:39 +0700188 "Identify subscriber by IMSI\n"
189 "IMSI/MSISDN/ID of the subscriber\n"
190 "Create subscriber by IMSI\n")
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200191{
192 int rc;
193 struct hlr_subscriber subscr;
194 const char *imsi = argv[0];
195
196 if (!osmo_imsi_str_valid(imsi)) {
197 vty_out(vty, "%% Not a valid IMSI: %s%s", imsi, VTY_NEWLINE);
198 return CMD_WARNING;
199 }
200
201 rc = db_subscr_create(g_hlr->dbc, imsi);
202
203 if (rc) {
204 if (rc == -EEXIST)
205 vty_out(vty, "%% Subscriber already exists for IMSI = %s%s",
206 imsi, VTY_NEWLINE);
207 else
208 vty_out(vty, "%% Error (rc=%d): cannot create subscriber for IMSI = %s%s",
209 rc, imsi, VTY_NEWLINE);
210 return CMD_WARNING;
211 }
212
213 rc = db_subscr_get_by_imsi(g_hlr->dbc, imsi, &subscr);
214 vty_out(vty, "%% Created subscriber %s%s", imsi, VTY_NEWLINE);
215
216 subscr_dump_full_vty(vty, &subscr);
217
218 return CMD_SUCCESS;
219}
220
221DEFUN(subscriber_delete,
222 subscriber_delete_cmd,
223 SUBSCR "delete",
224 SUBSCR_HELP "Delete subscriber from database\n")
225{
226 struct hlr_subscriber subscr;
227 int rc;
228 const char *id_type = argv[0];
229 const char *id = argv[1];
230
231 /* Find out the IMSI regardless of which way the caller decided to
232 * identify the subscriber by. */
233 if (get_subscr_by_argv(vty, id_type, id, &subscr))
234 return CMD_WARNING;
235
236 rc = db_subscr_delete_by_id(g_hlr->dbc, subscr.id);
237 if (rc) {
238 vty_out(vty, "%% Error: Failed to remove subscriber for IMSI '%s'%s",
239 subscr.imsi, VTY_NEWLINE);
240 return CMD_WARNING;
241 }
242
243 vty_out(vty, "%% Deleted subscriber for IMSI '%s'%s", subscr.imsi, VTY_NEWLINE);
244 return CMD_SUCCESS;
245}
246
247DEFUN(subscriber_msisdn,
248 subscriber_msisdn_cmd,
Neels Hofmeyra820ea12018-12-02 19:46:46 +0100249 SUBSCR_UPDATE "msisdn (none|MSISDN)",
250 SUBSCR_UPDATE_HELP SUBSCR_MSISDN_HELP
251 "Remove MSISDN (phone number)\n"
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200252 "New MSISDN (phone number)\n")
253{
254 struct hlr_subscriber subscr;
255 const char *id_type = argv[0];
256 const char *id = argv[1];
257 const char *msisdn = argv[2];
258
Neels Hofmeyra820ea12018-12-02 19:46:46 +0100259 if (strcmp(msisdn, "none") == 0)
260 msisdn = NULL;
261 else {
262 if (strlen(msisdn) > sizeof(subscr.msisdn) - 1) {
263 vty_out(vty, "%% MSISDN is too long, max. %zu characters are allowed%s",
264 sizeof(subscr.msisdn)-1, VTY_NEWLINE);
265 return CMD_WARNING;
266 }
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200267
Neels Hofmeyra820ea12018-12-02 19:46:46 +0100268 if (!osmo_msisdn_str_valid(msisdn)) {
269 vty_out(vty, "%% MSISDN invalid: '%s'%s", msisdn, VTY_NEWLINE);
270 return CMD_WARNING;
271 }
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200272 }
273
274 if (get_subscr_by_argv(vty, id_type, id, &subscr))
275 return CMD_WARNING;
276
277 if (db_subscr_update_msisdn_by_imsi(g_hlr->dbc, subscr.imsi, msisdn)) {
278 vty_out(vty, "%% Error: cannot update MSISDN for subscriber IMSI='%s'%s",
279 subscr.imsi, VTY_NEWLINE);
280 return CMD_WARNING;
281 }
282
Neels Hofmeyra820ea12018-12-02 19:46:46 +0100283 if (msisdn) {
284 vty_out(vty, "%% Updated subscriber IMSI='%s' to MSISDN='%s'%s",
285 subscr.imsi, msisdn, VTY_NEWLINE);
Stefan Sperlingf1622522018-04-09 11:39:16 +0200286
Neels Hofmeyra820ea12018-12-02 19:46:46 +0100287 if (db_subscr_get_by_msisdn(g_hlr->dbc, msisdn, &subscr) == 0)
288 osmo_hlr_subscriber_update_notify(&subscr);
289 } else {
290 vty_out(vty, "%% Updated subscriber IMSI='%s': removed MSISDN%s",
291 subscr.imsi, VTY_NEWLINE);
292
Stefan Sperlingf1622522018-04-09 11:39:16 +0200293 osmo_hlr_subscriber_update_notify(&subscr);
Neels Hofmeyra820ea12018-12-02 19:46:46 +0100294 }
Stefan Sperlingf1622522018-04-09 11:39:16 +0200295
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200296 return CMD_SUCCESS;
297}
298
299static bool is_hexkey_valid(struct vty *vty, const char *label,
300 const char *hex_str, int minlen, int maxlen)
301{
302 if (osmo_is_hexstr(hex_str, minlen * 2, maxlen * 2, true))
303 return true;
304 vty_out(vty, "%% Invalid value for %s: '%s'%s", label, hex_str, VTY_NEWLINE);
305 return false;
306}
307
308#define AUTH_ALG_TYPES_2G "(comp128v1|comp128v2|comp128v3|xor)"
309#define AUTH_ALG_TYPES_2G_HELP \
310 "Use COMP128v1 algorithm\n" \
311 "Use COMP128v2 algorithm\n" \
312 "Use COMP128v3 algorithm\n" \
313 "Use XOR algorithm\n"
314
315#define AUTH_ALG_TYPES_3G "milenage"
316#define AUTH_ALG_TYPES_3G_HELP \
317 "Use Milenage algorithm\n"
318
319#define A38_XOR_MIN_KEY_LEN 12
320#define A38_XOR_MAX_KEY_LEN 16
321#define A38_COMP128_KEY_LEN 16
322
323#define MILENAGE_KEY_LEN 16
324
325static bool auth_algo_parse(const char *alg_str, enum osmo_auth_algo *algo,
326 int *minlen, int *maxlen)
327{
328 if (!strcasecmp(alg_str, "none")) {
329 *algo = OSMO_AUTH_ALG_NONE;
330 *minlen = *maxlen = 0;
331 } else if (!strcasecmp(alg_str, "comp128v1")) {
332 *algo = OSMO_AUTH_ALG_COMP128v1;
333 *minlen = *maxlen = A38_COMP128_KEY_LEN;
334 } else if (!strcasecmp(alg_str, "comp128v2")) {
335 *algo = OSMO_AUTH_ALG_COMP128v2;
336 *minlen = *maxlen = A38_COMP128_KEY_LEN;
337 } else if (!strcasecmp(alg_str, "comp128v3")) {
338 *algo = OSMO_AUTH_ALG_COMP128v3;
339 *minlen = *maxlen = A38_COMP128_KEY_LEN;
340 } else if (!strcasecmp(alg_str, "xor")) {
341 *algo = OSMO_AUTH_ALG_XOR;
342 *minlen = A38_XOR_MIN_KEY_LEN;
343 *maxlen = A38_XOR_MAX_KEY_LEN;
344 } else if (!strcasecmp(alg_str, "milenage")) {
345 *algo = OSMO_AUTH_ALG_MILENAGE;
346 *minlen = *maxlen = MILENAGE_KEY_LEN;
347 } else
348 return false;
349 return true;
350}
351
352DEFUN(subscriber_no_aud2g,
353 subscriber_no_aud2g_cmd,
354 SUBSCR_UPDATE "aud2g none",
355 SUBSCR_UPDATE_HELP
356 "Set 2G authentication data\n"
357 "Delete 2G authentication data\n")
358{
359 struct hlr_subscriber subscr;
360 int rc;
361 const char *id_type = argv[0];
362 const char *id = argv[1];
363 struct sub_auth_data_str aud = {
364 .type = OSMO_AUTH_TYPE_GSM,
365 .algo = OSMO_AUTH_ALG_NONE,
366 };
367
368 if (get_subscr_by_argv(vty, id_type, id, &subscr))
369 return CMD_WARNING;
370
371 rc = db_subscr_update_aud_by_id(g_hlr->dbc, subscr.id, &aud);
372
Harald Welte880a34d2018-03-01 21:32:01 +0100373 if (rc && rc != -ENOENT) {
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200374 vty_out(vty, "%% Error: cannot disable 2G auth data for IMSI='%s'%s",
375 subscr.imsi, VTY_NEWLINE);
376 return CMD_WARNING;
377 }
378 return CMD_SUCCESS;
379}
380
381DEFUN(subscriber_aud2g,
382 subscriber_aud2g_cmd,
383 SUBSCR_UPDATE "aud2g " AUTH_ALG_TYPES_2G " ki KI",
384 SUBSCR_UPDATE_HELP
385 "Set 2G authentication data\n"
386 AUTH_ALG_TYPES_2G_HELP
387 "Set Ki Encryption Key\n" "Ki as 32 hexadecimal characters\n")
388{
389 struct hlr_subscriber subscr;
390 int rc;
391 int minlen = 0;
392 int maxlen = 0;
393 const char *id_type = argv[0];
394 const char *id = argv[1];
395 const char *alg_type = argv[2];
396 const char *ki = argv[3];
397 struct sub_auth_data_str aud2g = {
398 .type = OSMO_AUTH_TYPE_GSM,
399 .u.gsm.ki = ki,
400 };
401
402 if (!auth_algo_parse(alg_type, &aud2g.algo, &minlen, &maxlen)) {
403 vty_out(vty, "%% Unknown auth algorithm: '%s'%s", alg_type, VTY_NEWLINE);
404 return CMD_WARNING;
405 }
406
407 if (!is_hexkey_valid(vty, "KI", aud2g.u.gsm.ki, minlen, maxlen))
408 return CMD_WARNING;
409
410 if (get_subscr_by_argv(vty, id_type, id, &subscr))
411 return CMD_WARNING;
412
413 rc = db_subscr_update_aud_by_id(g_hlr->dbc, subscr.id, &aud2g);
414
415 if (rc) {
416 vty_out(vty, "%% Error: cannot set 2G auth data for IMSI='%s'%s",
417 subscr.imsi, VTY_NEWLINE);
418 return CMD_WARNING;
419 }
420 return CMD_SUCCESS;
421}
422
423DEFUN(subscriber_no_aud3g,
424 subscriber_no_aud3g_cmd,
425 SUBSCR_UPDATE "aud3g none",
426 SUBSCR_UPDATE_HELP
427 "Set UMTS authentication data (3G, and 2G with UMTS AKA)\n"
428 "Delete 3G authentication data\n")
429{
430 struct hlr_subscriber subscr;
431 int rc;
432 const char *id_type = argv[0];
433 const char *id = argv[1];
434 struct sub_auth_data_str aud = {
435 .type = OSMO_AUTH_TYPE_UMTS,
436 .algo = OSMO_AUTH_ALG_NONE,
437 };
438
439 if (get_subscr_by_argv(vty, id_type, id, &subscr))
440 return CMD_WARNING;
441
442 rc = db_subscr_update_aud_by_id(g_hlr->dbc, subscr.id, &aud);
443
Harald Welte880a34d2018-03-01 21:32:01 +0100444 if (rc && rc != -ENOENT) {
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200445 vty_out(vty, "%% Error: cannot disable 3G auth data for IMSI='%s'%s",
446 subscr.imsi, VTY_NEWLINE);
447 return CMD_WARNING;
448 }
449 return CMD_SUCCESS;
450}
451
452DEFUN(subscriber_aud3g,
453 subscriber_aud3g_cmd,
454 SUBSCR_UPDATE "aud3g " AUTH_ALG_TYPES_3G
455 " k K"
456 " (op|opc) OP_C"
457 " [ind-bitlen] [<0-28>]",
458 SUBSCR_UPDATE_HELP
459 "Set UMTS authentication data (3G, and 2G with UMTS AKA)\n"
460 AUTH_ALG_TYPES_3G_HELP
461 "Set Encryption Key K\n" "K as 32 hexadecimal characters\n"
462 "Set OP key\n" "Set OPC key\n" "OP or OPC as 32 hexadecimal characters\n"
463 "Set IND bit length\n" "IND bit length value (default: 5)\n")
464{
465 struct hlr_subscriber subscr;
466 int minlen = 0;
467 int maxlen = 0;
468 int rc;
469 const char *id_type = argv[0];
470 const char *id = argv[1];
471 const char *alg_type = AUTH_ALG_TYPES_3G;
472 const char *k = argv[2];
473 bool opc_is_op = (strcasecmp("op", argv[3]) == 0);
474 const char *op_opc = argv[4];
475 int ind_bitlen = argc > 6? atoi(argv[6]) : 5;
476 struct sub_auth_data_str aud3g = {
477 .type = OSMO_AUTH_TYPE_UMTS,
478 .u.umts = {
479 .k = k,
480 .opc_is_op = opc_is_op,
481 .opc = op_opc,
482 .ind_bitlen = ind_bitlen,
483 },
484 };
485
486 if (!auth_algo_parse(alg_type, &aud3g.algo, &minlen, &maxlen)) {
487 vty_out(vty, "%% Unknown auth algorithm: '%s'%s", alg_type, VTY_NEWLINE);
488 return CMD_WARNING;
489 }
490
491 if (!is_hexkey_valid(vty, "K", aud3g.u.umts.k, minlen, maxlen))
492 return CMD_WARNING;
493
494 if (!is_hexkey_valid(vty, opc_is_op ? "OP" : "OPC", aud3g.u.umts.opc,
495 MILENAGE_KEY_LEN, MILENAGE_KEY_LEN))
496 return CMD_WARNING;
497
498 if (get_subscr_by_argv(vty, id_type, id, &subscr))
499 return CMD_WARNING;
500
501 rc = db_subscr_update_aud_by_id(g_hlr->dbc, subscr.id, &aud3g);
502
503 if (rc) {
504 vty_out(vty, "%% Error: cannot set 3G auth data for IMSI='%s'%s",
505 subscr.imsi, VTY_NEWLINE);
506 return CMD_WARNING;
507 }
508 return CMD_SUCCESS;
509}
510
Harald Welted5807b82018-07-29 12:27:41 +0200511void hlr_vty_subscriber_init(void)
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200512{
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200513 install_element_ve(&subscriber_show_cmd);
Neels Hofmeyr8aa780b2018-12-02 18:52:49 +0100514 install_element_ve(&show_subscriber_cmd);
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200515 install_element(ENABLE_NODE, &subscriber_create_cmd);
516 install_element(ENABLE_NODE, &subscriber_delete_cmd);
517 install_element(ENABLE_NODE, &subscriber_msisdn_cmd);
518 install_element(ENABLE_NODE, &subscriber_no_aud2g_cmd);
519 install_element(ENABLE_NODE, &subscriber_aud2g_cmd);
520 install_element(ENABLE_NODE, &subscriber_no_aud3g_cmd);
521 install_element(ENABLE_NODE, &subscriber_aud3g_cmd);
522}