layer23 manual network search: Fixed searching behavior.
[osmocom-bb.git] / src / host / layer23 / src / vty_interface.c
1 /*
2  * (C) 2010 by Andreas Eversberg <jolly@eversberg.eu>
3  *
4  * All Rights Reserved
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  *
20  */
21
22 #include <string.h>
23 #include <stdlib.h>
24 #include <stdarg.h>
25 #include <unistd.h>
26 #include <sys/types.h>
27
28 #include <vty/command.h>
29 #include <vty/buffer.h>
30 #include <vty/vty.h>
31
32 #include <osmocore/gsm48.h>
33 #include <osmocom/osmocom_data.h>
34 #include <osmocom/networks.h>
35 #include <osmocom/mncc.h>
36 #include <osmocom/transaction.h>
37
38 int mncc_call(struct osmocom_ms *ms, char *number);
39 int mncc_hangup(struct osmocom_ms *ms);
40 int mncc_answer(struct osmocom_ms *ms);
41
42 extern struct llist_head ms_list;
43
44 struct cmd_node ms_node = {
45         MS_NODE,
46         "%s(ms)#",
47         1
48 };
49
50 struct cmd_node testsim_node = {
51         TESTSIM_NODE,
52         "%s(test-sim)#",
53         1
54 };
55
56 static void print_vty(void *priv, const char *fmt, ...)
57 {
58         char buffer[1000];
59         struct vty *vty = priv;
60         va_list args;
61
62         va_start(args, fmt);
63         vsnprintf(buffer, sizeof(buffer) - 1, fmt, args);
64         buffer[sizeof(buffer) - 1] = '\0';
65         va_end(args);
66
67         if (buffer[0]) {
68                 if (buffer[strlen(buffer) - 1] == '\n') {
69                         buffer[strlen(buffer) - 1] = '\0';
70                         vty_out(vty, "%s%s", buffer, VTY_NEWLINE);
71                 } else
72                         vty_out(vty, "%s", buffer);
73         }
74 }
75
76 static struct osmocom_ms *get_ms(const char *name, struct vty *vty)
77 {
78         struct osmocom_ms *ms;
79
80         llist_for_each_entry(ms, &ms_list, entity) {
81                 if (!strcmp(ms->name, name))
82                         return ms;
83         }
84         vty_out(vty, "MS name '%s' does not exits.%s", name, VTY_NEWLINE);
85
86         return NULL;
87 }
88
89 DEFUN(show_ms, show_ms_cmd, "show ms",
90         SHOW_STR "Display available MS entities\n")
91 {
92         struct osmocom_ms *ms;
93
94         llist_for_each_entry(ms, &ms_list, entity) {
95                 struct gsm_settings *set = &ms->settings;
96
97                 vty_out(vty, "MS NAME: %s%s", ms->name, VTY_NEWLINE);
98                 vty_out(vty, " IMEI: %s%s", set->imei, VTY_NEWLINE);
99                 vty_out(vty, " IMEISV: %s%s", set->imeisv, VTY_NEWLINE);
100                 if (set->imei_random)
101                         vty_out(vty, " IMEI generation: random (%d trailing "
102                                 "digits)%s", set->imei_random, VTY_NEWLINE);
103                 else
104                         vty_out(vty, " IMEI generation: fixed%s", VTY_NEWLINE);
105                 vty_out(vty, " network selection mode: %s%s",
106                         (set->plmn_mode == PLMN_MODE_AUTO)
107                                 ? "automatic" : "manual", VTY_NEWLINE);
108         }
109
110         return CMD_SUCCESS;
111 }
112
113 DEFUN(show_support, show_support_cmd, "show support [ms_name]",
114         SHOW_STR "Display information about MS support\n"
115         "Name of MS (see \"show ms\")")
116 {
117         struct osmocom_ms *ms;
118
119         if (argc) {
120                 ms = get_ms(argv[0], vty);
121                 if (!ms)
122                         return CMD_WARNING;
123                 gsm_support_dump(&ms->support, print_vty, vty);
124         } else {
125                 llist_for_each_entry(ms, &ms_list, entity) {
126                         gsm_support_dump(&ms->support, print_vty, vty);
127                         vty_out(vty, "%s", VTY_NEWLINE);
128                 }
129         }
130
131         return CMD_SUCCESS;
132 }
133
134 static void gsm_states_dump(struct osmocom_ms *ms, struct vty *vty)
135 {
136         struct gsm_trans *trans;
137
138         vty_out(vty, "Current state of MS '%s'%s", ms->name, VTY_NEWLINE);
139         if (ms->settings.plmn_mode == PLMN_MODE_AUTO)
140                 vty_out(vty, " automatic network selection: %s%s", 
141                         plmn_a_state_names[ms->plmn.state], VTY_NEWLINE);
142         else
143                 vty_out(vty, " manual network selection: %s%s", 
144                         plmn_m_state_names[ms->plmn.state], VTY_NEWLINE);
145         vty_out(vty, " cell selection: %s%s", 
146                 cs_state_names[ms->cellsel.state], VTY_NEWLINE);
147         vty_out(vty, " radio ressource layer: %s%s", 
148                 gsm48_rr_state_names[ms->rrlayer.state], VTY_NEWLINE);
149         vty_out(vty, " mobility management layer: %s", 
150                 gsm48_mm_state_names[ms->mmlayer.state]);
151         if (ms->mmlayer.state == GSM48_MM_ST_MM_IDLE)
152                 vty_out(vty, ", %s", 
153                         gsm48_mm_substate_names[ms->mmlayer.substate]);
154         vty_out(vty, "%s", VTY_NEWLINE);
155         llist_for_each_entry(trans, &ms->trans_list, entry) {
156                 vty_out(vty, " call control: %s%s", 
157                         gsm48_cc_state_name(trans->cc.state), VTY_NEWLINE);
158         }
159 }
160
161 DEFUN(show_states, show_states_cmd, "show states [ms_name]",
162         SHOW_STR "Display current states of given MS\n"
163         "Name of MS (see \"show ms\")")
164 {
165         struct osmocom_ms *ms;
166
167         if (argc) {
168                 ms = get_ms(argv[0], vty);
169                 if (!ms)
170                         return CMD_WARNING;
171                 gsm_states_dump(ms, vty);
172         } else {
173                 llist_for_each_entry(ms, &ms_list, entity) {
174                         gsm_states_dump(ms, vty);
175                         vty_out(vty, "%s", VTY_NEWLINE);
176                 }
177         }
178
179         return CMD_SUCCESS;
180 }
181
182 DEFUN(show_subscr, show_subscr_cmd, "show subscriber [ms_name]",
183         SHOW_STR "Display information about subscriber\n"
184         "Name of MS (see \"show ms\")")
185 {
186         struct osmocom_ms *ms;
187
188         if (argc) {
189                 ms = get_ms(argv[0], vty);
190                 if (!ms)
191                         return CMD_WARNING;
192                 gsm_subscr_dump(&ms->subscr, print_vty, vty);
193         } else {
194                 llist_for_each_entry(ms, &ms_list, entity) {
195                         gsm_subscr_dump(&ms->subscr, print_vty, vty);
196                         vty_out(vty, "%s", VTY_NEWLINE);
197                 }
198         }
199
200         return CMD_SUCCESS;
201 }
202
203 DEFUN(show_cell, show_cell_cmd, "show cell MS_NAME",
204         SHOW_STR "Display information about received cells\n"
205         "Name of MS (see \"show ms\")")
206 {
207         struct osmocom_ms *ms;
208
209         ms = get_ms(argv[0], vty);
210         if (!ms)
211                 return CMD_WARNING;
212
213         gsm322_dump_cs_list(&ms->cellsel, GSM322_CS_FLAG_SYSINFO, print_vty,
214                 vty);
215
216         return CMD_SUCCESS;
217 }
218
219 DEFUN(show_cell_si, show_cell_si_cmd, "show cell MS_NAME <0-1023>",
220         SHOW_STR "Display information about received cell\n"
221         "Name of MS (see \"show ms\")\nRadio frequency number")
222 {
223         struct osmocom_ms *ms;
224         int i;
225         struct gsm48_sysinfo *s;
226
227         ms = get_ms(argv[0], vty);
228         if (!ms)
229                 return CMD_WARNING;
230
231         i = atoi(argv[1]);
232         if (i < 0 || i > 1023) {
233                 vty_out(vty, "Given ARFCN '%s' not in range (0..1023)%s",
234                         argv[1], VTY_NEWLINE);
235                 return CMD_WARNING;
236         }
237         s = ms->cellsel.list[i].sysinfo;
238         if (!s) {
239                 vty_out(vty, "Given ARFCN '%s' has no sysinfo available%s",
240                         argv[1], VTY_NEWLINE);
241                 return CMD_SUCCESS;
242         }
243
244         gsm48_sysinfo_dump(s, i, print_vty, vty);
245
246         return CMD_SUCCESS;
247 }
248
249 DEFUN(show_ba, show_ba_cmd, "show ba MS_NAME [mcc] [mnc]",
250         SHOW_STR "Display information about band allocations\n"
251         "Name of MS (see \"show ms\")\nMobile Country Code\n"
252         "Mobile Network Code")
253 {
254         struct osmocom_ms *ms;
255         uint16_t mcc = 0, mnc = 0;
256
257         ms = get_ms(argv[0], vty);
258         if (!ms)
259                 return CMD_WARNING;
260
261         if (argc >= 3) {
262                 mcc = atoi(argv[1]);
263                 mnc = atoi(argv[2]);
264         }
265
266         gsm322_dump_ba_list(&ms->cellsel, mcc, mnc, print_vty, vty);
267
268         return CMD_SUCCESS;
269 }
270
271 DEFUN(show_forb_plmn, show_forb_plmn_cmd, "show forbidden plmn MS_NAME",
272         SHOW_STR "Display information about forbidden cells / networks\n"
273         "Display forbidden PLMNs\nName of MS (see \"show ms\")")
274 {
275         struct osmocom_ms *ms;
276
277         ms = get_ms(argv[0], vty);
278         if (!ms)
279                 return CMD_WARNING;
280
281         gsm_subscr_dump_forbidden_plmn(ms, print_vty, vty);
282
283         return CMD_SUCCESS;
284 }
285
286 DEFUN(show_forb_la, show_forb_la_cmd, "show forbidden location-area MS_NAME",
287         SHOW_STR "Display information about forbidden cells / networks\n"
288         "Display forbidden location areas\nName of MS (see \"show ms\")")
289 {
290         struct osmocom_ms *ms;
291
292         ms = get_ms(argv[0], vty);
293         if (!ms)
294                 return CMD_WARNING;
295
296         gsm322_dump_forbidden_la(ms, print_vty, vty);
297
298         return CMD_SUCCESS;
299 }
300
301 DEFUN(insert_test, insert_test_cmd, "insert testcard MS_NAME [mcc] [mnc]",
302         "Insert ...\nInsert test card\nName of MS (see \"show ms\")\n"
303         "Mobile Country Code\nMobile Network Code")
304 {
305         struct osmocom_ms *ms;
306         uint16_t mcc = 1, mnc = 1;
307
308         ms = get_ms(argv[0], vty);
309         if (!ms)
310                 return CMD_WARNING;
311
312         if (ms->subscr.sim_valid) {
313                 vty_out(vty, "Sim already presend, remove first!%s",
314                         VTY_NEWLINE);
315                 return CMD_WARNING;
316         }
317
318         if (argc >= 3) {
319                 mcc = atoi(argv[1]);
320                 mnc = atoi(argv[2]);
321         }
322
323         gsm_subscr_testcard(ms);
324
325         return CMD_SUCCESS;
326 }
327
328 DEFUN(remove_sim, remove_sim_cmd, "remove sim MS_NAME",
329         "Remove ...\nRemove SIM card\nName of MS (see \"show ms\")")
330 {
331         struct osmocom_ms *ms;
332
333         ms = get_ms(argv[0], vty);
334         if (!ms)
335                 return CMD_WARNING;
336
337         if (!ms->subscr.sim_valid) {
338                 vty_out(vty, "No Sim inserted!%s", VTY_NEWLINE);
339                 return CMD_WARNING;
340         }
341
342         gsm_subscr_remove(ms);
343
344         return CMD_SUCCESS;
345 }
346
347 DEFUN(network_select, network_select_cmd, "network select MS_NAME MCC MNC",
348         "Select ...\nSelect Network\nName of MS (see \"show ms\")\n"
349         "Mobile Country Code\nMobile Network Code")
350 {
351         struct osmocom_ms *ms;
352         struct gsm322_plmn *plmn;
353         struct msgb *nmsg;
354         struct gsm322_msg *ngm;
355         struct gsm322_plmn_list *temp;
356         uint16_t mcc, mnc;
357         int found = 0;
358
359         ms = get_ms(argv[0], vty);
360         if (!ms)
361                 return CMD_WARNING;
362         plmn = &ms->plmn;
363
364         mcc = atoi(argv[1]);
365         mnc = atoi(argv[2]);
366
367         llist_for_each_entry(temp, &plmn->sorted_plmn, entry)
368                 if (temp->mcc == mcc &&  temp->mnc == mnc)
369                         found = 1;
370         if (!found) {
371                 vty_out(vty, "Network not in list!%s", VTY_NEWLINE);
372                 return CMD_WARNING;
373         }
374
375         nmsg = gsm322_msgb_alloc(GSM322_EVENT_CHOSE_PLMN);
376         if (!nmsg)
377                 return CMD_WARNING;
378         ngm = (struct gsm322_msg *) nmsg->data;
379         ngm->mcc = mcc;
380         ngm->mnc = mnc;
381         gsm322_plmn_sendmsg(ms, nmsg);
382
383         return CMD_SUCCESS;
384 }
385
386 DEFUN(call, call_cmd, "call MS_NAME (NUMBER|emergency|answer|hangup)",
387         "Make a call\nName of MS (see \"show ms\")\nPhone number to call\n"
388         "Make an emergency call\nAnswer an incomming call\nHangup a call")
389 {
390         struct osmocom_ms *ms;
391
392         ms = get_ms(argv[0], vty);
393         if (!ms)
394                 return CMD_WARNING;
395
396         switch (argv[1][0]) {
397         case 'a':
398                 mncc_answer(ms);
399                 break;
400         case 'h':
401                 mncc_hangup(ms);
402                 break;
403         default:
404                 mncc_call(ms, (char *)argv[1]);
405         }
406
407         return CMD_SUCCESS;
408 }
409
410 DEFUN(network_show, network_show_cmd, "network show MS_NAME",
411         "Network ...\nShow results of network search (again)\n"
412         "Name of MS (see \"show ms\")")
413 {
414         struct osmocom_ms *ms;
415         struct gsm322_plmn *plmn;
416         struct gsm322_plmn_list *temp;
417
418         ms = get_ms(argv[0], vty);
419         if (!ms)
420                 return CMD_WARNING;
421         plmn = &ms->plmn;
422
423         if (ms->settings.plmn_mode != PLMN_MODE_AUTO
424          && plmn->state != GSM322_M3_NOT_ON_PLMN) {
425                 vty_out(vty, "Start network search first!%s", VTY_NEWLINE);
426                 return CMD_WARNING;
427         }
428
429         llist_for_each_entry(temp, &plmn->sorted_plmn, entry)
430                 vty_out(vty, " Network %03d, %02d (%s, %s)%s", temp->mcc,
431                         temp->mnc, gsm_get_mcc(temp->mcc),
432                         gsm_get_mnc(temp->mcc, temp->mnc), VTY_NEWLINE);
433
434         return CMD_SUCCESS;
435 }
436
437 DEFUN(network_search, network_search_cmd, "network search MS_NAME",
438         "Network ...\nTrigger network search\nName of MS (see \"show ms\")")
439 {
440         struct osmocom_ms *ms;
441         struct msgb *nmsg;
442
443         ms = get_ms(argv[0], vty);
444         if (!ms)
445                 return CMD_WARNING;
446
447         nmsg = gsm322_msgb_alloc(GSM322_EVENT_USER_RESEL);
448         if (!nmsg)
449                 return CMD_WARNING;
450         gsm322_plmn_sendmsg(ms, nmsg);
451
452         return CMD_SUCCESS;
453 }
454
455 /* per MS config */
456 DEFUN(cfg_ms, cfg_ms_cmd, "ms MS_NAME",
457         "Select a mobile station to configure\nName of MS (see \"show ms\")")
458 {
459         struct osmocom_ms *ms;
460
461         ms = get_ms(argv[0], vty);
462         if (!ms)
463                 return CMD_WARNING;
464
465         vty->index = ms;
466         vty->node = MS_NODE;
467
468         return CMD_SUCCESS;
469 }
470
471 static void config_write_ms_single(struct vty *vty, struct osmocom_ms *ms)
472 {
473         struct gsm_settings *set = &ms->settings;
474
475         vty_out(vty, "ms %s%s", ms->name, VTY_NEWLINE);
476         switch(ms->settings.simtype) {
477                 case GSM_SIM_TYPE_NONE:
478                 vty_out(vty, " sim none%s", VTY_NEWLINE);
479                 break;
480                 case GSM_SIM_TYPE_SLOT:
481                 vty_out(vty, " sim slot%s", VTY_NEWLINE);
482                 break;
483                 case GSM_SIM_TYPE_TEST:
484                 vty_out(vty, " sim test%s", VTY_NEWLINE);
485                 break;
486         }
487         vty_out(vty, " network-selection-mode %s%s", (set->plmn_mode
488                         == PLMN_MODE_AUTO) ? "auto" : "manual", VTY_NEWLINE);
489         vty_out(vty, " imei %s %s%s", set->imei,
490                 set->imeisv + strlen(set->imei), VTY_NEWLINE);
491         if (set->imei_random)
492                 vty_out(vty, " imei-random %d%s", set->imei_random,
493                         VTY_NEWLINE);
494         else
495                 vty_out(vty, " imei-fixed%s", VTY_NEWLINE);
496         vty_out(vty, " emergency-imsi %s%s", (ms->settings.emergency_imsi[0]) ?
497                 ms->settings.emergency_imsi : "none", VTY_NEWLINE);
498         vty_out(vty, " test-sim%s", VTY_NEWLINE);
499         vty_out(vty, "  imsi %s%s", ms->settings.test_imsi, VTY_NEWLINE);
500         vty_out(vty, "  %sbarred-access%s", (set->test_barr) ? "" : "no ",
501                 VTY_NEWLINE);
502         if (ms->settings.test_rplmn_valid)
503                 vty_out(vty, "  rplmn %03d %02d%s", ms->settings.test_rplmn_mcc,
504                         ms->settings.test_rplmn_mnc, VTY_NEWLINE);
505         else
506                 vty_out(vty, "  no rplmn%s", VTY_NEWLINE);
507         vty_out(vty, "  hplmn-search %s%s", (set->test_always) ? "everywhere"
508                         : "foreign-country", VTY_NEWLINE);
509         vty_out(vty, " exit%s", VTY_NEWLINE);
510         vty_out(vty, "exit%s", VTY_NEWLINE);
511         vty_out(vty, "!%s", VTY_NEWLINE);
512 }
513
514 static int config_write_ms(struct vty *vty)
515 {
516         struct osmocom_ms *ms;
517
518         llist_for_each_entry(ms, &ms_list, entity)
519                 config_write_ms_single(vty, ms);
520
521         return CMD_SUCCESS;
522 }
523
524 DEFUN(cfg_ms_mode, cfg_ms_mode_cmd, "network-selection-mode (auto|manual)",
525         "Set network selection mode\nAutomatic network selection\n"
526         "Manual network selection")
527 {
528         struct osmocom_ms *ms = vty->index;
529         struct msgb *nmsg;
530
531         if (!ms->plmn.state) {
532                 if (argv[0][0] == 'a')
533                         ms->settings.plmn_mode = PLMN_MODE_AUTO;
534                 else
535                         ms->settings.plmn_mode = PLMN_MODE_MANUAL;
536
537                 return CMD_SUCCESS;
538         }
539         if (argv[0][0] == 'a')
540                 nmsg = gsm322_msgb_alloc(GSM322_EVENT_SEL_AUTO);
541         else
542                 nmsg = gsm322_msgb_alloc(GSM322_EVENT_SEL_MANUAL);
543         if (!nmsg)
544                 return CMD_WARNING;
545         gsm322_plmn_sendmsg(ms, nmsg);
546
547         return CMD_SUCCESS;
548 }
549
550 DEFUN(cfg_ms_imei, cfg_ms_imei_cmd, "imei IMEI [SV]",
551         "Set IMEI (enter without control digit)\n15 Digits IMEI\n"
552         "Software version digit")
553 {
554         struct osmocom_ms *ms = vty->index;
555         char *error, *sv = "0";
556
557         if (argc >= 2)
558                 sv = (char *)argv[1];
559
560         error = gsm_check_imei(argv[0], sv);
561         if (error) {
562                 vty_out(vty, "%s%s", error, VTY_NEWLINE);
563                 return CMD_WARNING;
564         }
565
566         strcpy(ms->settings.imei, argv[0]);
567         strcpy(ms->settings.imeisv, argv[0]);
568         strcpy(ms->settings.imeisv + 15, sv);
569
570         return CMD_SUCCESS;
571 }
572
573 DEFUN(cfg_ms_imei_fixed, cfg_ms_imei_fixed_cmd, "imei-fixed",
574         "Use fixed IMEI on every power on")
575 {
576         struct osmocom_ms *ms = vty->index;
577
578         ms->settings.imei_random = 0;
579
580         return CMD_SUCCESS;
581 }
582
583 DEFUN(cfg_ms_imei_random, cfg_ms_imei_random_cmd, "imei-random <0-15>",
584         "Use random IMEI on every power on\n"
585         "Number of trailing digits to randomize")
586 {
587         struct osmocom_ms *ms = vty->index;
588
589         ms->settings.imei_random = atoi(argv[0]);
590
591         return CMD_SUCCESS;
592 }
593
594 DEFUN(cfg_ms_emerg_imsi, cfg_ms_emerg_imsi_cmd, "emergency-imsi (none|IMSI)",
595         "Use IMSI for emergency calls\n"
596         "Use IMSI of SIM or IMEI for emergency calls\n15 digits IMSI")
597 {
598         struct osmocom_ms *ms = vty->index;
599         uint16_t mcc, mnc;
600         char *error;
601
602         if (argv[0][0] == 'n') {
603                 ms->settings.emergency_imsi[0] = '\0';
604                 return CMD_SUCCESS;
605         }
606
607         error = gsm_check_imsi(argv[0], &mcc, &mnc);
608         if (error) {
609                 vty_out(vty, "%s%s", error, VTY_NEWLINE);
610                 return CMD_WARNING;
611         }
612         strcpy(ms->settings.emergency_imsi, argv[0]);
613
614         return CMD_SUCCESS;
615 }
616
617 DEFUN(cfg_ms_sim, cfg_ms_sim_cmd, "sim (none|test)",
618         "Set sim card type when powering on\nNo sim interted\n"
619         "Test sim inserted")
620 {
621         struct osmocom_ms *ms = vty->index;
622
623         switch (argv[0][0]) {
624         case 'n':
625                 ms->settings.simtype = GSM_SIM_TYPE_NONE;
626                 break;
627         case 's':
628                 ms->settings.simtype = GSM_SIM_TYPE_SLOT;
629                 break;
630         case 't':
631                 ms->settings.simtype = GSM_SIM_TYPE_TEST;
632                 break;
633         }
634
635         return CMD_SUCCESS;
636 }
637
638 /* per MS config */
639 DEFUN(cfg_testsim, cfg_testsim_cmd, "test-sim",
640         "Configure test SIM emulation")
641 {
642         vty->node = TESTSIM_NODE;
643
644         return CMD_SUCCESS;
645 }
646
647 static int config_write_dummy(struct vty *vty)
648 {
649         return CMD_SUCCESS;
650 }
651
652 DEFUN(cfg_test_imsi, cfg_test_imsi_cmd, "imsi IMSI",
653         "Set IMSI on test card\n15 digits IMSI")
654 {
655         struct osmocom_ms *ms = vty->index;
656         uint16_t mcc, mnc;
657         char *error = gsm_check_imsi(argv[0], &mcc, &mnc);
658
659         if (error) {
660                 vty_out(vty, "%s%s", error, VTY_NEWLINE);
661                 return CMD_WARNING;
662         }
663
664         strcpy(ms->settings.test_imsi, argv[0]);
665
666         return CMD_SUCCESS;
667 }
668
669 DEFUN(cfg_test_barr, cfg_test_barr_cmd, "barred-access",
670         "Allow access to barred cells")
671 {
672         struct osmocom_ms *ms = vty->index;
673
674         ms->settings.test_barr = 1;
675
676         return CMD_SUCCESS;
677 }
678
679 DEFUN(cfg_test_no_barr, cfg_test_no_barr_cmd, "no barred-access",
680         NO_STR "Deny access to barred cells")
681 {
682         struct osmocom_ms *ms = vty->index;
683
684         ms->settings.test_barr = 0;
685
686         return CMD_SUCCESS;
687 }
688
689 DEFUN(cfg_test_no_rplmn, cfg_test_no_rplmn_cmd, "no rplmn",
690         NO_STR "Unset Registered PLMN")
691 {
692         struct osmocom_ms *ms = vty->index;
693
694         ms->settings.test_rplmn_valid = 0;
695
696         return CMD_SUCCESS;
697 }
698
699 DEFUN(cfg_test_rplmn, cfg_test_rplmn_cmd, "rplmn MCC MNC",
700         "Set Registered PLMN\nMobile Country Code\nMobile Network Code")
701 {
702         struct osmocom_ms *ms = vty->index;
703
704         ms->settings.test_rplmn_valid = 1;
705         ms->settings.test_rplmn_mcc = atoi(argv[0]);
706         ms->settings.test_rplmn_mnc = atoi(argv[1]);
707
708         return CMD_SUCCESS;
709 }
710
711 DEFUN(cfg_test_hplmn, cfg_test_hplmn_cmd, "hplmn-search (everywhere|foreign-country)",
712         "Set Home PLMN search mode\n"
713         "Search for HPLMN when on any other network\n"
714         "Search for HPLMN when in a different country")
715 {
716         struct osmocom_ms *ms = vty->index;
717
718         switch (argv[0][0]) {
719         case 'e':
720                 ms->settings.test_always = 1;
721                 break;
722         case 'f':
723                 ms->settings.test_always = 0;
724                 break;
725         }
726
727         return CMD_SUCCESS;
728 }
729
730 int ms_vty_init(void)
731 {
732         cmd_init(1);
733         vty_init();
734
735         install_element(ENABLE_NODE, &show_ms_cmd);
736         install_element(VIEW_NODE, &show_ms_cmd);
737         install_element(ENABLE_NODE, &show_subscr_cmd);
738         install_element(VIEW_NODE, &show_subscr_cmd);
739         install_element(ENABLE_NODE, &show_support_cmd);
740         install_element(VIEW_NODE, &show_support_cmd);
741         install_element(ENABLE_NODE, &show_states_cmd);
742         install_element(VIEW_NODE, &show_states_cmd);
743         install_element(ENABLE_NODE, &show_cell_cmd);
744         install_element(VIEW_NODE, &show_cell_cmd);
745         install_element(ENABLE_NODE, &show_cell_si_cmd);
746         install_element(VIEW_NODE, &show_cell_si_cmd);
747         install_element(ENABLE_NODE, &show_ba_cmd);
748         install_element(VIEW_NODE, &show_ba_cmd);
749         install_element(ENABLE_NODE, &show_forb_la_cmd);
750         install_element(VIEW_NODE, &show_forb_la_cmd);
751         install_element(ENABLE_NODE, &show_forb_plmn_cmd);
752         install_element(VIEW_NODE, &show_forb_plmn_cmd);
753
754         install_element(ENABLE_NODE, &insert_test_cmd);
755         install_element(ENABLE_NODE, &remove_sim_cmd);
756         install_element(ENABLE_NODE, &network_search_cmd);
757         install_element(ENABLE_NODE, &network_show_cmd);
758         install_element(ENABLE_NODE, &network_select_cmd);
759         install_element(ENABLE_NODE, &call_cmd);
760
761         install_element(CONFIG_NODE, &cfg_ms_cmd);
762         install_node(&ms_node, config_write_ms);
763         install_default(MS_NODE);
764         install_element(MS_NODE, &cfg_ms_mode_cmd);
765         install_element(MS_NODE, &cfg_ms_imei_cmd);
766         install_element(MS_NODE, &cfg_ms_imei_fixed_cmd);
767         install_element(MS_NODE, &cfg_ms_imei_random_cmd);
768         install_element(MS_NODE, &cfg_ms_emerg_imsi_cmd);
769         install_element(MS_NODE, &cfg_ms_sim_cmd);
770
771         install_element(MS_NODE, &cfg_testsim_cmd);
772         install_node(&testsim_node, config_write_dummy);
773         install_default(TESTSIM_NODE);
774         install_element(TESTSIM_NODE, &cfg_test_imsi_cmd);
775         install_element(TESTSIM_NODE, &cfg_test_barr_cmd);
776         install_element(TESTSIM_NODE, &cfg_test_no_barr_cmd);
777         install_element(TESTSIM_NODE, &cfg_test_no_rplmn_cmd);
778         install_element(TESTSIM_NODE, &cfg_test_rplmn_cmd);
779         install_element(TESTSIM_NODE, &cfg_test_hplmn_cmd);
780
781         return 0;
782 }
783