blob: c2359d4d19255f48da7220eabcc66f9367859ab8 [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
Neels Hofmeyr18a1b012018-12-25 17:23:41 +010038static char *get_datestr(const time_t *t)
Stefan Sperling5c14c9c2018-12-07 12:30:21 +010039{
Neels Hofmeyr18a1b012018-12-25 17:23:41 +010040 static char buf[32];
41 struct tm tm;
Stefan Sperling5c14c9c2018-12-07 12:30:21 +010042
Neels Hofmeyr18a1b012018-12-25 17:23:41 +010043 tm = *gmtime(t);
44
45 strftime(buf, sizeof(buf), "%FT%T+00:00", &tm);
46 return buf;
Stefan Sperling5c14c9c2018-12-07 12:30:21 +010047}
48
Neels Hofmeyr183e7002017-10-06 02:59:54 +020049static void subscr_dump_full_vty(struct vty *vty, struct hlr_subscriber *subscr)
50{
51 int rc;
52 struct osmo_sub_auth_data aud2g;
53 struct osmo_sub_auth_data aud3g;
54
55 vty_out(vty, " ID: %"PRIu64"%s", subscr->id, VTY_NEWLINE);
56
Neels Hofmeyr36bec872017-10-23 18:44:23 +020057 vty_out(vty, " IMSI: %s%s", *subscr->imsi ? subscr->imsi : "none", VTY_NEWLINE);
Neels Hofmeyr183e7002017-10-06 02:59:54 +020058 vty_out(vty, " MSISDN: %s%s", *subscr->msisdn ? subscr->msisdn : "none", VTY_NEWLINE);
59 if (*subscr->vlr_number)
60 vty_out(vty, " VLR number: %s%s", subscr->vlr_number, VTY_NEWLINE);
61 if (*subscr->sgsn_number)
62 vty_out(vty, " SGSN number: %s%s", subscr->sgsn_number, VTY_NEWLINE);
63 if (*subscr->sgsn_address)
64 vty_out(vty, " SGSN address: %s%s", subscr->sgsn_address, VTY_NEWLINE);
65 if (subscr->periodic_lu_timer)
66 vty_out(vty, " Periodic LU timer: %u%s", subscr->periodic_lu_timer, VTY_NEWLINE);
67 if (subscr->periodic_rau_tau_timer)
68 vty_out(vty, " Periodic RAU/TAU timer: %u%s", subscr->periodic_rau_tau_timer, VTY_NEWLINE);
69 if (subscr->lmsi)
70 vty_out(vty, " LMSI: %x%s", subscr->lmsi, VTY_NEWLINE);
71 if (!subscr->nam_cs)
72 vty_out(vty, " CS disabled%s", VTY_NEWLINE);
73 if (subscr->ms_purged_cs)
74 vty_out(vty, " CS purged%s", VTY_NEWLINE);
75 if (!subscr->nam_ps)
76 vty_out(vty, " PS disabled%s", VTY_NEWLINE);
77 if (subscr->ms_purged_ps)
78 vty_out(vty, " PS purged%s", VTY_NEWLINE);
Stefan Sperling5c14c9c2018-12-07 12:30:21 +010079 if (subscr->last_lu_seen)
Neels Hofmeyr18a1b012018-12-25 17:23:41 +010080 vty_out(vty, " last LU seen: %s%s", get_datestr(&subscr->last_lu_seen), VTY_NEWLINE);
Neels Hofmeyr183e7002017-10-06 02:59:54 +020081
82 if (!*subscr->imsi)
83 return;
84
85 OSMO_ASSERT(g_hlr);
86 rc = db_get_auth_data(g_hlr->dbc, subscr->imsi, &aud2g, &aud3g, NULL);
87
Neels Hofmeyrbd1dca02017-11-23 15:25:30 +010088 switch (rc) {
89 case 0:
90 break;
91 case -ENOENT:
92 case -ENOKEY:
93 aud2g.algo = OSMO_AUTH_ALG_NONE;
94 aud3g.algo = OSMO_AUTH_ALG_NONE;
95 break;
96 default:
97 vty_out(vty, "%% Error retrieving data from database (%d)%s", rc, VTY_NEWLINE);
98 return;
Neels Hofmeyr183e7002017-10-06 02:59:54 +020099 }
100
101 if (aud2g.type != OSMO_AUTH_TYPE_NONE && aud2g.type != OSMO_AUTH_TYPE_GSM) {
102 vty_out(vty, "%% Error: 2G auth data is not of type 'GSM'%s", VTY_NEWLINE);
103 aud2g = (struct osmo_sub_auth_data){};
104 }
105
106 if (aud3g.type != OSMO_AUTH_TYPE_NONE && aud3g.type != OSMO_AUTH_TYPE_UMTS) {
107 vty_out(vty, "%% Error: 3G auth data is not of type 'UMTS'%s", VTY_NEWLINE);
108 aud3g = (struct osmo_sub_auth_data){};
109 }
110
111 if (aud2g.algo != OSMO_AUTH_ALG_NONE && aud2g.type != OSMO_AUTH_TYPE_NONE) {
112 vty_out(vty, " 2G auth: %s%s",
113 osmo_auth_alg_name(aud2g.algo), VTY_NEWLINE);
114 vty_out(vty, " KI=%s%s",
115 hexdump_buf(aud2g.u.gsm.ki), VTY_NEWLINE);
116 }
117
118 if (aud3g.algo != OSMO_AUTH_ALG_NONE && aud3g.type != OSMO_AUTH_TYPE_NONE) {
119 vty_out(vty, " 3G auth: %s%s", osmo_auth_alg_name(aud3g.algo), VTY_NEWLINE);
120 vty_out(vty, " K=%s%s", hexdump_buf(aud3g.u.umts.k), VTY_NEWLINE);
121 vty_out(vty, " %s=%s%s", aud3g.u.umts.opc_is_op? "OP" : "OPC",
122 hexdump_buf(aud3g.u.umts.opc), VTY_NEWLINE);
123 vty_out(vty, " IND-bitlen=%u", aud3g.u.umts.ind_bitlen);
124 if (aud3g.u.umts.sqn)
125 vty_out(vty, " last-SQN=%"PRIu64, aud3g.u.umts.sqn);
126 vty_out(vty, VTY_NEWLINE);
127 }
128}
129
130static int get_subscr_by_argv(struct vty *vty, const char *type, const char *id, struct hlr_subscriber *subscr)
131{
132 int rc = -1;
133 if (strcmp(type, "imsi") == 0)
134 rc = db_subscr_get_by_imsi(g_hlr->dbc, id, subscr);
135 else if (strcmp(type, "msisdn") == 0)
136 rc = db_subscr_get_by_msisdn(g_hlr->dbc, id, subscr);
137 else if (strcmp(type, "id") == 0)
138 rc = db_subscr_get_by_id(g_hlr->dbc, atoll(id), subscr);
139 if (rc)
140 vty_out(vty, "%% No subscriber for %s = '%s'%s",
141 type, id, VTY_NEWLINE);
142 return rc;
143}
144
145#define SUBSCR_CMD "subscriber "
146#define SUBSCR_CMD_HELP "Subscriber management commands\n"
147
Neels Hofmeyr8aa780b2018-12-02 18:52:49 +0100148#define SUBSCR_ID "(imsi|msisdn|id) IDENT"
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200149#define SUBSCR_ID_HELP \
150 "Identify subscriber by IMSI\n" \
151 "Identify subscriber by MSISDN (phone number)\n" \
152 "Identify subscriber by database ID\n" \
153 "IMSI/MSISDN/ID of the subscriber\n"
154
Neels Hofmeyr8aa780b2018-12-02 18:52:49 +0100155#define SUBSCR SUBSCR_CMD SUBSCR_ID " "
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200156#define SUBSCR_HELP SUBSCR_CMD_HELP SUBSCR_ID_HELP
157
158#define SUBSCR_UPDATE SUBSCR "update "
159#define SUBSCR_UPDATE_HELP SUBSCR_HELP "Set or update subscriber data\n"
Neels Hofmeyra820ea12018-12-02 19:46:46 +0100160#define SUBSCR_MSISDN_HELP "Set MSISDN (phone number) of the subscriber\n"
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200161
162DEFUN(subscriber_show,
163 subscriber_show_cmd,
164 SUBSCR "show",
165 SUBSCR_HELP "Show subscriber information\n")
166{
167 struct hlr_subscriber subscr;
168 const char *id_type = argv[0];
169 const char *id = argv[1];
170
171 if (get_subscr_by_argv(vty, id_type, id, &subscr))
172 return CMD_WARNING;
173
174 subscr_dump_full_vty(vty, &subscr);
175 return CMD_SUCCESS;
176}
177
Neels Hofmeyr8aa780b2018-12-02 18:52:49 +0100178ALIAS(subscriber_show, show_subscriber_cmd,
179 "show " SUBSCR_CMD SUBSCR_ID,
180 SHOW_STR SUBSCR_CMD_HELP SUBSCR_ID_HELP);
181
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200182DEFUN(subscriber_create,
183 subscriber_create_cmd,
184 SUBSCR_CMD "imsi IDENT create",
185 SUBSCR_CMD_HELP
Vadim Yanitskiyf473c7b2018-07-30 14:29:39 +0700186 "Identify subscriber by IMSI\n"
187 "IMSI/MSISDN/ID of the subscriber\n"
188 "Create subscriber by IMSI\n")
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200189{
190 int rc;
191 struct hlr_subscriber subscr;
192 const char *imsi = argv[0];
193
194 if (!osmo_imsi_str_valid(imsi)) {
195 vty_out(vty, "%% Not a valid IMSI: %s%s", imsi, VTY_NEWLINE);
196 return CMD_WARNING;
197 }
198
199 rc = db_subscr_create(g_hlr->dbc, imsi);
200
201 if (rc) {
202 if (rc == -EEXIST)
203 vty_out(vty, "%% Subscriber already exists for IMSI = %s%s",
204 imsi, VTY_NEWLINE);
205 else
206 vty_out(vty, "%% Error (rc=%d): cannot create subscriber for IMSI = %s%s",
207 rc, imsi, VTY_NEWLINE);
208 return CMD_WARNING;
209 }
210
211 rc = db_subscr_get_by_imsi(g_hlr->dbc, imsi, &subscr);
212 vty_out(vty, "%% Created subscriber %s%s", imsi, VTY_NEWLINE);
213
214 subscr_dump_full_vty(vty, &subscr);
215
216 return CMD_SUCCESS;
217}
218
219DEFUN(subscriber_delete,
220 subscriber_delete_cmd,
221 SUBSCR "delete",
222 SUBSCR_HELP "Delete subscriber from database\n")
223{
224 struct hlr_subscriber subscr;
225 int rc;
226 const char *id_type = argv[0];
227 const char *id = argv[1];
228
229 /* Find out the IMSI regardless of which way the caller decided to
230 * identify the subscriber by. */
231 if (get_subscr_by_argv(vty, id_type, id, &subscr))
232 return CMD_WARNING;
233
234 rc = db_subscr_delete_by_id(g_hlr->dbc, subscr.id);
235 if (rc) {
236 vty_out(vty, "%% Error: Failed to remove subscriber for IMSI '%s'%s",
237 subscr.imsi, VTY_NEWLINE);
238 return CMD_WARNING;
239 }
240
241 vty_out(vty, "%% Deleted subscriber for IMSI '%s'%s", subscr.imsi, VTY_NEWLINE);
242 return CMD_SUCCESS;
243}
244
245DEFUN(subscriber_msisdn,
246 subscriber_msisdn_cmd,
Neels Hofmeyra820ea12018-12-02 19:46:46 +0100247 SUBSCR_UPDATE "msisdn (none|MSISDN)",
248 SUBSCR_UPDATE_HELP SUBSCR_MSISDN_HELP
249 "Remove MSISDN (phone number)\n"
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200250 "New MSISDN (phone number)\n")
251{
252 struct hlr_subscriber subscr;
253 const char *id_type = argv[0];
254 const char *id = argv[1];
255 const char *msisdn = argv[2];
256
Neels Hofmeyra820ea12018-12-02 19:46:46 +0100257 if (strcmp(msisdn, "none") == 0)
258 msisdn = NULL;
259 else {
260 if (strlen(msisdn) > sizeof(subscr.msisdn) - 1) {
261 vty_out(vty, "%% MSISDN is too long, max. %zu characters are allowed%s",
262 sizeof(subscr.msisdn)-1, VTY_NEWLINE);
263 return CMD_WARNING;
264 }
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200265
Neels Hofmeyra820ea12018-12-02 19:46:46 +0100266 if (!osmo_msisdn_str_valid(msisdn)) {
267 vty_out(vty, "%% MSISDN invalid: '%s'%s", msisdn, VTY_NEWLINE);
268 return CMD_WARNING;
269 }
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200270 }
271
272 if (get_subscr_by_argv(vty, id_type, id, &subscr))
273 return CMD_WARNING;
274
275 if (db_subscr_update_msisdn_by_imsi(g_hlr->dbc, subscr.imsi, msisdn)) {
276 vty_out(vty, "%% Error: cannot update MSISDN for subscriber IMSI='%s'%s",
277 subscr.imsi, VTY_NEWLINE);
278 return CMD_WARNING;
279 }
280
Neels Hofmeyra820ea12018-12-02 19:46:46 +0100281 if (msisdn) {
282 vty_out(vty, "%% Updated subscriber IMSI='%s' to MSISDN='%s'%s",
283 subscr.imsi, msisdn, VTY_NEWLINE);
Stefan Sperlingf1622522018-04-09 11:39:16 +0200284
Neels Hofmeyra820ea12018-12-02 19:46:46 +0100285 if (db_subscr_get_by_msisdn(g_hlr->dbc, msisdn, &subscr) == 0)
286 osmo_hlr_subscriber_update_notify(&subscr);
287 } else {
288 vty_out(vty, "%% Updated subscriber IMSI='%s': removed MSISDN%s",
289 subscr.imsi, VTY_NEWLINE);
290
Stefan Sperlingf1622522018-04-09 11:39:16 +0200291 osmo_hlr_subscriber_update_notify(&subscr);
Neels Hofmeyra820ea12018-12-02 19:46:46 +0100292 }
Stefan Sperlingf1622522018-04-09 11:39:16 +0200293
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200294 return CMD_SUCCESS;
295}
296
297static bool is_hexkey_valid(struct vty *vty, const char *label,
298 const char *hex_str, int minlen, int maxlen)
299{
300 if (osmo_is_hexstr(hex_str, minlen * 2, maxlen * 2, true))
301 return true;
302 vty_out(vty, "%% Invalid value for %s: '%s'%s", label, hex_str, VTY_NEWLINE);
303 return false;
304}
305
306#define AUTH_ALG_TYPES_2G "(comp128v1|comp128v2|comp128v3|xor)"
307#define AUTH_ALG_TYPES_2G_HELP \
308 "Use COMP128v1 algorithm\n" \
309 "Use COMP128v2 algorithm\n" \
310 "Use COMP128v3 algorithm\n" \
311 "Use XOR algorithm\n"
312
313#define AUTH_ALG_TYPES_3G "milenage"
314#define AUTH_ALG_TYPES_3G_HELP \
315 "Use Milenage algorithm\n"
316
317#define A38_XOR_MIN_KEY_LEN 12
318#define A38_XOR_MAX_KEY_LEN 16
319#define A38_COMP128_KEY_LEN 16
320
321#define MILENAGE_KEY_LEN 16
322
323static bool auth_algo_parse(const char *alg_str, enum osmo_auth_algo *algo,
324 int *minlen, int *maxlen)
325{
326 if (!strcasecmp(alg_str, "none")) {
327 *algo = OSMO_AUTH_ALG_NONE;
328 *minlen = *maxlen = 0;
329 } else if (!strcasecmp(alg_str, "comp128v1")) {
330 *algo = OSMO_AUTH_ALG_COMP128v1;
331 *minlen = *maxlen = A38_COMP128_KEY_LEN;
332 } else if (!strcasecmp(alg_str, "comp128v2")) {
333 *algo = OSMO_AUTH_ALG_COMP128v2;
334 *minlen = *maxlen = A38_COMP128_KEY_LEN;
335 } else if (!strcasecmp(alg_str, "comp128v3")) {
336 *algo = OSMO_AUTH_ALG_COMP128v3;
337 *minlen = *maxlen = A38_COMP128_KEY_LEN;
338 } else if (!strcasecmp(alg_str, "xor")) {
339 *algo = OSMO_AUTH_ALG_XOR;
340 *minlen = A38_XOR_MIN_KEY_LEN;
341 *maxlen = A38_XOR_MAX_KEY_LEN;
342 } else if (!strcasecmp(alg_str, "milenage")) {
343 *algo = OSMO_AUTH_ALG_MILENAGE;
344 *minlen = *maxlen = MILENAGE_KEY_LEN;
345 } else
346 return false;
347 return true;
348}
349
350DEFUN(subscriber_no_aud2g,
351 subscriber_no_aud2g_cmd,
352 SUBSCR_UPDATE "aud2g none",
353 SUBSCR_UPDATE_HELP
354 "Set 2G authentication data\n"
355 "Delete 2G authentication data\n")
356{
357 struct hlr_subscriber subscr;
358 int rc;
359 const char *id_type = argv[0];
360 const char *id = argv[1];
361 struct sub_auth_data_str aud = {
362 .type = OSMO_AUTH_TYPE_GSM,
363 .algo = OSMO_AUTH_ALG_NONE,
364 };
365
366 if (get_subscr_by_argv(vty, id_type, id, &subscr))
367 return CMD_WARNING;
368
369 rc = db_subscr_update_aud_by_id(g_hlr->dbc, subscr.id, &aud);
370
Harald Welte880a34d2018-03-01 21:32:01 +0100371 if (rc && rc != -ENOENT) {
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200372 vty_out(vty, "%% Error: cannot disable 2G auth data for IMSI='%s'%s",
373 subscr.imsi, VTY_NEWLINE);
374 return CMD_WARNING;
375 }
376 return CMD_SUCCESS;
377}
378
379DEFUN(subscriber_aud2g,
380 subscriber_aud2g_cmd,
381 SUBSCR_UPDATE "aud2g " AUTH_ALG_TYPES_2G " ki KI",
382 SUBSCR_UPDATE_HELP
383 "Set 2G authentication data\n"
384 AUTH_ALG_TYPES_2G_HELP
385 "Set Ki Encryption Key\n" "Ki as 32 hexadecimal characters\n")
386{
387 struct hlr_subscriber subscr;
388 int rc;
389 int minlen = 0;
390 int maxlen = 0;
391 const char *id_type = argv[0];
392 const char *id = argv[1];
393 const char *alg_type = argv[2];
394 const char *ki = argv[3];
395 struct sub_auth_data_str aud2g = {
396 .type = OSMO_AUTH_TYPE_GSM,
397 .u.gsm.ki = ki,
398 };
399
400 if (!auth_algo_parse(alg_type, &aud2g.algo, &minlen, &maxlen)) {
401 vty_out(vty, "%% Unknown auth algorithm: '%s'%s", alg_type, VTY_NEWLINE);
402 return CMD_WARNING;
403 }
404
405 if (!is_hexkey_valid(vty, "KI", aud2g.u.gsm.ki, minlen, maxlen))
406 return CMD_WARNING;
407
408 if (get_subscr_by_argv(vty, id_type, id, &subscr))
409 return CMD_WARNING;
410
411 rc = db_subscr_update_aud_by_id(g_hlr->dbc, subscr.id, &aud2g);
412
413 if (rc) {
414 vty_out(vty, "%% Error: cannot set 2G auth data for IMSI='%s'%s",
415 subscr.imsi, VTY_NEWLINE);
416 return CMD_WARNING;
417 }
418 return CMD_SUCCESS;
419}
420
421DEFUN(subscriber_no_aud3g,
422 subscriber_no_aud3g_cmd,
423 SUBSCR_UPDATE "aud3g none",
424 SUBSCR_UPDATE_HELP
425 "Set UMTS authentication data (3G, and 2G with UMTS AKA)\n"
426 "Delete 3G authentication data\n")
427{
428 struct hlr_subscriber subscr;
429 int rc;
430 const char *id_type = argv[0];
431 const char *id = argv[1];
432 struct sub_auth_data_str aud = {
433 .type = OSMO_AUTH_TYPE_UMTS,
434 .algo = OSMO_AUTH_ALG_NONE,
435 };
436
437 if (get_subscr_by_argv(vty, id_type, id, &subscr))
438 return CMD_WARNING;
439
440 rc = db_subscr_update_aud_by_id(g_hlr->dbc, subscr.id, &aud);
441
Harald Welte880a34d2018-03-01 21:32:01 +0100442 if (rc && rc != -ENOENT) {
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200443 vty_out(vty, "%% Error: cannot disable 3G auth data for IMSI='%s'%s",
444 subscr.imsi, VTY_NEWLINE);
445 return CMD_WARNING;
446 }
447 return CMD_SUCCESS;
448}
449
450DEFUN(subscriber_aud3g,
451 subscriber_aud3g_cmd,
452 SUBSCR_UPDATE "aud3g " AUTH_ALG_TYPES_3G
453 " k K"
454 " (op|opc) OP_C"
455 " [ind-bitlen] [<0-28>]",
456 SUBSCR_UPDATE_HELP
457 "Set UMTS authentication data (3G, and 2G with UMTS AKA)\n"
458 AUTH_ALG_TYPES_3G_HELP
459 "Set Encryption Key K\n" "K as 32 hexadecimal characters\n"
460 "Set OP key\n" "Set OPC key\n" "OP or OPC as 32 hexadecimal characters\n"
461 "Set IND bit length\n" "IND bit length value (default: 5)\n")
462{
463 struct hlr_subscriber subscr;
464 int minlen = 0;
465 int maxlen = 0;
466 int rc;
467 const char *id_type = argv[0];
468 const char *id = argv[1];
469 const char *alg_type = AUTH_ALG_TYPES_3G;
470 const char *k = argv[2];
471 bool opc_is_op = (strcasecmp("op", argv[3]) == 0);
472 const char *op_opc = argv[4];
473 int ind_bitlen = argc > 6? atoi(argv[6]) : 5;
474 struct sub_auth_data_str aud3g = {
475 .type = OSMO_AUTH_TYPE_UMTS,
476 .u.umts = {
477 .k = k,
478 .opc_is_op = opc_is_op,
479 .opc = op_opc,
480 .ind_bitlen = ind_bitlen,
481 },
482 };
483
484 if (!auth_algo_parse(alg_type, &aud3g.algo, &minlen, &maxlen)) {
485 vty_out(vty, "%% Unknown auth algorithm: '%s'%s", alg_type, VTY_NEWLINE);
486 return CMD_WARNING;
487 }
488
489 if (!is_hexkey_valid(vty, "K", aud3g.u.umts.k, minlen, maxlen))
490 return CMD_WARNING;
491
492 if (!is_hexkey_valid(vty, opc_is_op ? "OP" : "OPC", aud3g.u.umts.opc,
493 MILENAGE_KEY_LEN, MILENAGE_KEY_LEN))
494 return CMD_WARNING;
495
496 if (get_subscr_by_argv(vty, id_type, id, &subscr))
497 return CMD_WARNING;
498
499 rc = db_subscr_update_aud_by_id(g_hlr->dbc, subscr.id, &aud3g);
500
501 if (rc) {
502 vty_out(vty, "%% Error: cannot set 3G auth data for IMSI='%s'%s",
503 subscr.imsi, VTY_NEWLINE);
504 return CMD_WARNING;
505 }
506 return CMD_SUCCESS;
507}
508
Harald Welted5807b82018-07-29 12:27:41 +0200509void hlr_vty_subscriber_init(void)
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200510{
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200511 install_element_ve(&subscriber_show_cmd);
Neels Hofmeyr8aa780b2018-12-02 18:52:49 +0100512 install_element_ve(&show_subscriber_cmd);
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200513 install_element(ENABLE_NODE, &subscriber_create_cmd);
514 install_element(ENABLE_NODE, &subscriber_delete_cmd);
515 install_element(ENABLE_NODE, &subscriber_msisdn_cmd);
516 install_element(ENABLE_NODE, &subscriber_no_aud2g_cmd);
517 install_element(ENABLE_NODE, &subscriber_aud2g_cmd);
518 install_element(ENABLE_NODE, &subscriber_no_aud3g_cmd);
519 install_element(ENABLE_NODE, &subscriber_aud3g_cmd);
520}