[layer23] Give ARFCN together with "show states <MS_NAME>"
[osmocom-bb.git] / src / host / layer23 / src / mobile / 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 <osmocore/utils.h>
29 #include <osmocore/gsm48.h>
30
31 #include <osmocom/bb/common/osmocom_data.h>
32 #include <osmocom/bb/common/networks.h>
33 #include <osmocom/bb/mobile/mncc.h>
34 #include <osmocom/bb/mobile/transaction.h>
35 #include <osmocom/bb/mobile/vty.h>
36 #include <osmocom/bb/mobile/gps.h>
37 #include <osmocom/vty/telnet_interface.h>
38
39 int mncc_call(struct osmocom_ms *ms, char *number);
40 int mncc_hangup(struct osmocom_ms *ms);
41 int mncc_answer(struct osmocom_ms *ms);
42 int mncc_hold(struct osmocom_ms *ms);
43 int mncc_retrieve(struct osmocom_ms *ms, int number);
44
45 extern struct llist_head ms_list;
46 extern struct llist_head active_connections;
47
48 struct cmd_node ms_node = {
49         MS_NODE,
50         "%s(ms)#",
51         1
52 };
53
54 struct cmd_node testsim_node = {
55         TESTSIM_NODE,
56         "%s(test-sim)#",
57         1
58 };
59
60 struct cmd_node support_node = {
61         SUPPORT_NODE,
62         "%s(support)#",
63         1
64 };
65
66 static void print_vty(void *priv, const char *fmt, ...)
67 {
68         char buffer[1000];
69         struct vty *vty = priv;
70         va_list args;
71
72         va_start(args, fmt);
73         vsnprintf(buffer, sizeof(buffer) - 1, fmt, args);
74         buffer[sizeof(buffer) - 1] = '\0';
75         va_end(args);
76
77         if (buffer[0]) {
78                 if (buffer[strlen(buffer) - 1] == '\n') {
79                         buffer[strlen(buffer) - 1] = '\0';
80                         vty_out(vty, "%s%s", buffer, VTY_NEWLINE);
81                 } else
82                         vty_out(vty, "%s", buffer);
83         }
84 }
85
86 int vty_reading = 0;
87
88 static void vty_restart(struct vty *vty)
89 {
90         if (vty_reading)
91                 return;
92         vty_out(vty, "You must restart for change to take effect!%s",
93                 VTY_NEWLINE);
94 }
95
96 static struct osmocom_ms *get_ms(const char *name, struct vty *vty)
97 {
98         struct osmocom_ms *ms;
99
100         llist_for_each_entry(ms, &ms_list, entity) {
101                 if (!strcmp(ms->name, name))
102                         return ms;
103         }
104         vty_out(vty, "MS name '%s' does not exits.%s", name, VTY_NEWLINE);
105
106         return NULL;
107 }
108
109 DEFUN(show_ms, show_ms_cmd, "show ms",
110         SHOW_STR "Display available MS entities\n")
111 {
112         struct osmocom_ms *ms;
113
114         llist_for_each_entry(ms, &ms_list, entity) {
115                 struct gsm_settings *set = &ms->settings;
116
117                 vty_out(vty, "MS NAME: %s%s", ms->name, VTY_NEWLINE);
118                 vty_out(vty, " IMEI: %s%s", set->imei, VTY_NEWLINE);
119                 vty_out(vty, " IMEISV: %s%s", set->imeisv, VTY_NEWLINE);
120                 if (set->imei_random)
121                         vty_out(vty, " IMEI generation: random (%d trailing "
122                                 "digits)%s", set->imei_random, VTY_NEWLINE);
123                 else
124                         vty_out(vty, " IMEI generation: fixed%s", VTY_NEWLINE);
125                 vty_out(vty, " network selection mode: %s%s",
126                         (set->plmn_mode == PLMN_MODE_AUTO)
127                                 ? "automatic" : "manual", VTY_NEWLINE);
128         }
129
130         return CMD_SUCCESS;
131 }
132
133 DEFUN(show_support, show_support_cmd, "show support [ms_name]",
134         SHOW_STR "Display information about MS support\n"
135         "Name of MS (see \"show ms\")")
136 {
137         struct osmocom_ms *ms;
138
139         if (argc) {
140                 ms = get_ms(argv[0], vty);
141                 if (!ms)
142                         return CMD_WARNING;
143                 gsm_support_dump(ms, print_vty, vty);
144         } else {
145                 llist_for_each_entry(ms, &ms_list, entity) {
146                         gsm_support_dump(ms, print_vty, vty);
147                         vty_out(vty, "%s", VTY_NEWLINE);
148                 }
149         }
150
151         return CMD_SUCCESS;
152 }
153
154 static void gsm_states_dump(struct osmocom_ms *ms, struct vty *vty)
155 {
156         struct gsm_settings *set = &ms->settings;
157         struct gsm_trans *trans;
158
159         vty_out(vty, "Current state of MS '%s'%s", ms->name, VTY_NEWLINE);
160         if (set->plmn_mode == PLMN_MODE_AUTO)
161                 vty_out(vty, " automatic network selection: %s%s", 
162                         plmn_a_state_names[ms->plmn.state], VTY_NEWLINE);
163         else
164                 vty_out(vty, " manual network selection: %s%s", 
165                         plmn_m_state_names[ms->plmn.state], VTY_NEWLINE);
166         vty_out(vty, " cell selection: %s",
167                 cs_state_names[ms->cellsel.state]);
168         if (ms->rrlayer.state == GSM48_RR_ST_IDLE && ms->cellsel.selected)
169                 vty_out(vty, " (ARFCN %d)", ms->cellsel.sel_arfcn);
170         vty_out(vty, "%s", VTY_NEWLINE);
171         vty_out(vty, " radio ressource layer: %s%s", 
172                 gsm48_rr_state_names[ms->rrlayer.state], VTY_NEWLINE);
173         vty_out(vty, " mobility management layer: %s", 
174                 gsm48_mm_state_names[ms->mmlayer.state]);
175         if (ms->mmlayer.state == GSM48_MM_ST_MM_IDLE)
176                 vty_out(vty, ", %s", 
177                         gsm48_mm_substate_names[ms->mmlayer.substate]);
178         vty_out(vty, "%s", VTY_NEWLINE);
179         llist_for_each_entry(trans, &ms->trans_list, entry) {
180                 vty_out(vty, " call control: %s%s", 
181                         gsm48_cc_state_name(trans->cc.state), VTY_NEWLINE);
182         }
183 }
184
185 DEFUN(show_states, show_states_cmd, "show states [ms_name]",
186         SHOW_STR "Display current states of given MS\n"
187         "Name of MS (see \"show ms\")")
188 {
189         struct osmocom_ms *ms;
190
191         if (argc) {
192                 ms = get_ms(argv[0], vty);
193                 if (!ms)
194                         return CMD_WARNING;
195                 gsm_states_dump(ms, vty);
196         } else {
197                 llist_for_each_entry(ms, &ms_list, entity) {
198                         gsm_states_dump(ms, vty);
199                         vty_out(vty, "%s", VTY_NEWLINE);
200                 }
201         }
202
203         return CMD_SUCCESS;
204 }
205
206 DEFUN(show_subscr, show_subscr_cmd, "show subscriber [ms_name]",
207         SHOW_STR "Display information about subscriber\n"
208         "Name of MS (see \"show ms\")")
209 {
210         struct osmocom_ms *ms;
211
212         if (argc) {
213                 ms = get_ms(argv[0], vty);
214                 if (!ms)
215                         return CMD_WARNING;
216                 gsm_subscr_dump(&ms->subscr, print_vty, vty);
217         } else {
218                 llist_for_each_entry(ms, &ms_list, entity) {
219                         gsm_subscr_dump(&ms->subscr, print_vty, vty);
220                         vty_out(vty, "%s", VTY_NEWLINE);
221                 }
222         }
223
224         return CMD_SUCCESS;
225 }
226
227 DEFUN(show_cell, show_cell_cmd, "show cell MS_NAME",
228         SHOW_STR "Display information about received cells\n"
229         "Name of MS (see \"show ms\")")
230 {
231         struct osmocom_ms *ms;
232
233         ms = get_ms(argv[0], vty);
234         if (!ms)
235                 return CMD_WARNING;
236
237         gsm322_dump_cs_list(&ms->cellsel, GSM322_CS_FLAG_SYSINFO, print_vty,
238                 vty);
239
240         return CMD_SUCCESS;
241 }
242
243 DEFUN(show_cell_si, show_cell_si_cmd, "show cell MS_NAME <0-1023>",
244         SHOW_STR "Display information about received cell\n"
245         "Name of MS (see \"show ms\")\nRadio frequency number")
246 {
247         struct osmocom_ms *ms;
248         int i;
249         struct gsm48_sysinfo *s;
250
251         ms = get_ms(argv[0], vty);
252         if (!ms)
253                 return CMD_WARNING;
254
255         i = atoi(argv[1]);
256         if (i < 0 || i > 1023) {
257                 vty_out(vty, "Given ARFCN '%s' not in range (0..1023)%s",
258                         argv[1], VTY_NEWLINE);
259                 return CMD_WARNING;
260         }
261         s = ms->cellsel.list[i].sysinfo;
262         if (!s) {
263                 vty_out(vty, "Given ARFCN '%s' has no sysinfo available%s",
264                         argv[1], VTY_NEWLINE);
265                 return CMD_SUCCESS;
266         }
267
268         gsm48_sysinfo_dump(s, i, print_vty, vty);
269
270         return CMD_SUCCESS;
271 }
272
273 DEFUN(show_ba, show_ba_cmd, "show ba MS_NAME [mcc] [mnc]",
274         SHOW_STR "Display information about band allocations\n"
275         "Name of MS (see \"show ms\")\nMobile Country Code\n"
276         "Mobile Network Code")
277 {
278         struct osmocom_ms *ms;
279         uint16_t mcc = 0, mnc = 0;
280
281         ms = get_ms(argv[0], vty);
282         if (!ms)
283                 return CMD_WARNING;
284
285         if (argc >= 3) {
286                 mcc = gsm_input_mcc((char *)argv[1]);
287                 mnc = gsm_input_mnc((char *)argv[2]);
288                 if (!mcc) {
289                         vty_out(vty, "Given MCC invalid%s", VTY_NEWLINE);
290                         return CMD_WARNING;
291                 }
292                 if (!mnc) {
293                         vty_out(vty, "Given MNC invalid%s", VTY_NEWLINE);
294                         return CMD_WARNING;
295                 }
296         }
297
298         gsm322_dump_ba_list(&ms->cellsel, mcc, mnc, print_vty, vty);
299
300         return CMD_SUCCESS;
301 }
302
303 DEFUN(show_forb_plmn, show_forb_plmn_cmd, "show forbidden plmn MS_NAME",
304         SHOW_STR "Display information about forbidden cells / networks\n"
305         "Display forbidden PLMNs\nName of MS (see \"show ms\")")
306 {
307         struct osmocom_ms *ms;
308
309         ms = get_ms(argv[0], vty);
310         if (!ms)
311                 return CMD_WARNING;
312
313         gsm_subscr_dump_forbidden_plmn(ms, print_vty, vty);
314
315         return CMD_SUCCESS;
316 }
317
318 DEFUN(show_forb_la, show_forb_la_cmd, "show forbidden location-area MS_NAME",
319         SHOW_STR "Display information about forbidden cells / networks\n"
320         "Display forbidden location areas\nName of MS (see \"show ms\")")
321 {
322         struct osmocom_ms *ms;
323
324         ms = get_ms(argv[0], vty);
325         if (!ms)
326                 return CMD_WARNING;
327
328         gsm322_dump_forbidden_la(ms, print_vty, vty);
329
330         return CMD_SUCCESS;
331 }
332
333 DEFUN(monitor_network, monitor_network_cmd, "monitor network MS_NAME",
334         "Monitor...\nMonitor network information\nName of MS (see \"show ms\")")
335 {
336         struct osmocom_ms *ms;
337
338         ms = get_ms(argv[0], vty);
339         if (!ms)
340                 return CMD_WARNING;
341
342         gsm48_rr_start_monitor(ms);
343
344         return CMD_SUCCESS;
345 }
346
347 DEFUN(no_monitor_network, no_monitor_network_cmd, "no monitor network MS_NAME",
348         NO_STR "Monitor...\nDeactivate monitor of network information\n"
349         "Name of MS (see \"show ms\")")
350 {
351         struct osmocom_ms *ms;
352
353         ms = get_ms(argv[0], vty);
354         if (!ms)
355                 return CMD_WARNING;
356
357         gsm48_rr_stop_monitor(ms);
358
359         return CMD_SUCCESS;
360 }
361
362 DEFUN(sim_test, sim_test_cmd, "sim testcard MS_NAME [mcc] [mnc]",
363         "SIM actions\nInsert test card\nName of MS (see \"show ms\")\n"
364         "Mobile Country Code of RPLMN\nMobile Network Code of RPLMN")
365 {
366         struct osmocom_ms *ms;
367         uint16_t mcc = 0x001, mnc = 0x01f;
368
369         ms = get_ms(argv[0], vty);
370         if (!ms)
371                 return CMD_WARNING;
372
373         if (ms->subscr.sim_valid) {
374                 vty_out(vty, "SIM already presend, remove first!%s",
375                         VTY_NEWLINE);
376                 return CMD_WARNING;
377         }
378
379         if (argc >= 3) {
380                 mcc = gsm_input_mcc((char *)argv[1]);
381                 mnc = gsm_input_mnc((char *)argv[2]);
382                 if (!mcc) {
383                         vty_out(vty, "Given MCC invalid%s", VTY_NEWLINE);
384                         return CMD_WARNING;
385                 }
386                 if (!mnc) {
387                         vty_out(vty, "Given MNC invalid%s", VTY_NEWLINE);
388                         return CMD_WARNING;
389                 }
390         }
391
392         gsm_subscr_testcard(ms, mcc, mnc);
393
394         return CMD_SUCCESS;
395 }
396
397 DEFUN(sim_reader, sim_reader_cmd, "sim reader MS_NAME",
398         "SIM actions\nSelect SIM from reader\nName of MS (see \"show ms\")")
399 {
400         struct osmocom_ms *ms;
401
402         ms = get_ms(argv[0], vty);
403         if (!ms)
404                 return CMD_WARNING;
405
406         if (ms->subscr.sim_valid) {
407                 vty_out(vty, "SIM already presend, remove first!%s",
408                         VTY_NEWLINE);
409                 return CMD_WARNING;
410         }
411
412         gsm_subscr_simcard(ms);
413
414         return CMD_SUCCESS;
415 }
416
417 DEFUN(sim_remove, sim_remove_cmd, "sim remove MS_NAME",
418         "SIM actions\nRemove SIM card\nName of MS (see \"show ms\")")
419 {
420         struct osmocom_ms *ms;
421
422         ms = get_ms(argv[0], vty);
423         if (!ms)
424                 return CMD_WARNING;
425
426         if (!ms->subscr.sim_valid) {
427                 vty_out(vty, "No Sim inserted!%s", VTY_NEWLINE);
428                 return CMD_WARNING;
429         }
430
431         gsm_subscr_remove(ms);
432
433         return CMD_SUCCESS;
434 }
435
436 DEFUN(sim_pin, sim_pin_cmd, "sim pin MS_NAME PIN",
437         "SIM actions\nEnter PIN for SIM card\nName of MS (see \"show ms\")\n"
438         "PIN number")
439 {
440         struct osmocom_ms *ms;
441
442         ms = get_ms(argv[0], vty);
443         if (!ms)
444                 return CMD_WARNING;
445
446         if (strlen(argv[1]) < 4 || strlen(argv[1]) > 8) {
447                 vty_out(vty, "PIN must be in range 4..8!%s", VTY_NEWLINE);
448                 return CMD_WARNING;
449         }
450
451         if (!ms->subscr.sim_pin_required) {
452                 vty_out(vty, "No PIN is required at this time!%s", VTY_NEWLINE);
453                 return CMD_WARNING;
454         }
455
456         gsm_subscr_sim_pin(ms, (char *)argv[1], "", 0);
457
458         return CMD_SUCCESS;
459 }
460
461 DEFUN(sim_disable_pin, sim_disable_pin_cmd, "sim disable-pin MS_NAME PIN",
462         "SIM actions\nDisable PIN of SIM card\nName of MS (see \"show ms\")\n"
463         "PIN number")
464 {
465         struct osmocom_ms *ms;
466
467         ms = get_ms(argv[0], vty);
468         if (!ms)
469                 return CMD_WARNING;
470
471         if (strlen(argv[1]) < 4 || strlen(argv[1]) > 8) {
472                 vty_out(vty, "PIN must be in range 4..8!%s", VTY_NEWLINE);
473                 return CMD_WARNING;
474         }
475
476         gsm_subscr_sim_pin(ms, (char *)argv[1], "", -1);
477
478         return CMD_SUCCESS;
479 }
480
481 DEFUN(sim_enable_pin, sim_enable_pin_cmd, "sim enable-pin MS_NAME PIN",
482         "SIM actions\nEnable PIN of SIM card\nName of MS (see \"show ms\")\n"
483         "PIN number")
484 {
485         struct osmocom_ms *ms;
486
487         ms = get_ms(argv[0], vty);
488         if (!ms)
489                 return CMD_WARNING;
490
491         if (strlen(argv[1]) < 4 || strlen(argv[1]) > 8) {
492                 vty_out(vty, "PIN must be in range 4..8!%s", VTY_NEWLINE);
493                 return CMD_WARNING;
494         }
495
496         gsm_subscr_sim_pin(ms, (char *)argv[1], "", 1);
497
498         return CMD_SUCCESS;
499 }
500
501 DEFUN(sim_change_pin, sim_change_pin_cmd, "sim change-pin MS_NAME OLD NEW",
502         "SIM actions\nChange PIN of SIM card\nName of MS (see \"show ms\")\n"
503         "Old PIN number\nNew PIN number")
504 {
505         struct osmocom_ms *ms;
506
507         ms = get_ms(argv[0], vty);
508         if (!ms)
509                 return CMD_WARNING;
510
511         if (strlen(argv[1]) < 4 || strlen(argv[1]) > 8) {
512                 vty_out(vty, "Old PIN must be in range 4..8!%s", VTY_NEWLINE);
513                 return CMD_WARNING;
514         }
515         if (strlen(argv[2]) < 4 || strlen(argv[2]) > 8) {
516                 vty_out(vty, "New PIN must be in range 4..8!%s", VTY_NEWLINE);
517                 return CMD_WARNING;
518         }
519
520         gsm_subscr_sim_pin(ms, (char *)argv[1], (char *)argv[2], 2);
521
522         return CMD_SUCCESS;
523 }
524
525 DEFUN(sim_unblock_pin, sim_unblock_pin_cmd, "sim unblock-pin MS_NAME PUC NEW",
526         "SIM actions\nChange PIN of SIM card\nName of MS (see \"show ms\")\n"
527         "Personal Unblock Key\nNew PIN number")
528 {
529         struct osmocom_ms *ms;
530
531         ms = get_ms(argv[0], vty);
532         if (!ms)
533                 return CMD_WARNING;
534
535         if (strlen(argv[1]) != 8) {
536                 vty_out(vty, "PUC must be 8 digits!%s", VTY_NEWLINE);
537                 return CMD_WARNING;
538         }
539         if (strlen(argv[2]) < 4 || strlen(argv[2]) > 8) {
540                 vty_out(vty, "PIN must be in range 4..8!%s", VTY_NEWLINE);
541                 return CMD_WARNING;
542         }
543
544         gsm_subscr_sim_pin(ms, (char *)argv[1], (char *)argv[2], 99);
545
546         return CMD_SUCCESS;
547 }
548
549 DEFUN(sim_lai, sim_lai_cmd, "sim lai MS_NAME MCC MNC LAC",
550         "SIM actions\nChange LAI of SIM card\nName of MS (see \"show ms\")\n"
551         "Mobile Country Code\nMobile Network Code\nLocation Area Code "
552         " (use 0000 to remove LAI)")
553 {
554         struct osmocom_ms *ms;
555         uint16_t mcc = gsm_input_mcc((char *)argv[1]),
556                  mnc = gsm_input_mnc((char *)argv[2]),
557                  lac = strtoul(argv[3], NULL, 16);
558
559         ms = get_ms(argv[0], vty);
560         if (!ms)
561                 return CMD_WARNING;
562
563         if (!mcc) {
564                 vty_out(vty, "Given MCC invalid%s", VTY_NEWLINE);
565                 return CMD_WARNING;
566         }
567         if (!mnc) {
568                 vty_out(vty, "Given MNC invalid%s", VTY_NEWLINE);
569                 return CMD_WARNING;
570         }
571
572         ms->subscr.mcc = mcc;
573         ms->subscr.mnc = mnc;
574         ms->subscr.lac = lac;
575         ms->subscr.tmsi = 0xffffffff;
576
577         gsm_subscr_write_loci(ms);
578
579         return CMD_SUCCESS;
580 }
581
582 DEFUN(network_select, network_select_cmd, "network select MS_NAME MCC MNC",
583         "Select ...\nSelect Network\nName of MS (see \"show ms\")\n"
584         "Mobile Country Code\nMobile Network Code")
585 {
586         struct osmocom_ms *ms;
587         struct gsm322_plmn *plmn;
588         struct msgb *nmsg;
589         struct gsm322_msg *ngm;
590         struct gsm322_plmn_list *temp;
591         uint16_t mcc = gsm_input_mcc((char *)argv[1]),
592                  mnc = gsm_input_mnc((char *)argv[2]);
593         int found = 0;
594
595         ms = get_ms(argv[0], vty);
596         if (!ms)
597                 return CMD_WARNING;
598         plmn = &ms->plmn;
599
600         if (!mcc) {
601                 vty_out(vty, "Given MCC invalid%s", VTY_NEWLINE);
602                 return CMD_WARNING;
603         }
604         if (!mnc) {
605                 vty_out(vty, "Given MNC invalid%s", VTY_NEWLINE);
606                 return CMD_WARNING;
607         }
608
609         llist_for_each_entry(temp, &plmn->sorted_plmn, entry)
610                 if (temp->mcc == mcc &&  temp->mnc == mnc)
611                         found = 1;
612         if (!found) {
613                 vty_out(vty, "Network not in list!%s", VTY_NEWLINE);
614                 return CMD_WARNING;
615         }
616
617         nmsg = gsm322_msgb_alloc(GSM322_EVENT_CHOOSE_PLMN);
618         if (!nmsg)
619                 return CMD_WARNING;
620         ngm = (struct gsm322_msg *) nmsg->data;
621         ngm->mcc = mcc;
622         ngm->mnc = mnc;
623         gsm322_plmn_sendmsg(ms, nmsg);
624
625         return CMD_SUCCESS;
626 }
627
628 DEFUN(call, call_cmd, "call MS_NAME (NUMBER|emergency|answer|hangup|hold)",
629         "Make a call\nName of MS (see \"show ms\")\nPhone number to call "
630         "(Use digits '0123456789*#abc', and '+' to dial international)\n"
631         "Make an emergency call\nAnswer an incomming call\nHangup a call\n"
632         "Hold current active call\n")
633 {
634         struct osmocom_ms *ms;
635         struct gsm_settings *set;
636         int i;
637
638         ms = get_ms(argv[0], vty);
639         if (!ms)
640                 return CMD_WARNING;
641         set = &ms->settings;
642
643         if (set->ch_cap == GSM_CAP_SDCCH) {
644                 vty_out(vty, "Basic call is not supported for SDCCH only "
645                         "mobile%s", VTY_NEWLINE);
646                 return CMD_WARNING;
647         }
648
649         if (!strcmp(argv[1], "emergency"))
650                 mncc_call(ms, (char *)argv[1]);
651         else switch (argv[1][0]) {
652         case 'a':
653                 mncc_answer(ms);
654                 break;
655         case 'h':
656                 if (argv[1][1] == 'a')
657                         mncc_hangup(ms);
658                 else
659                         mncc_hold(ms);
660                 break;
661         default:
662                 for (i = 0; i < strlen(argv[1]); i++) {
663                         /* allow international notation with + */
664                         if (i == 0 && argv[1][i] == '+')
665                                 continue;
666                         if (!(argv[1][i] >= '0' && argv[1][i] <= '9')
667                          && argv[1][i] != '*'
668                          && argv[1][i] != '#'
669                          && !(argv[1][i] >= 'a' && argv[1][i] <= 'c')) {
670                                 vty_out(vty, "Invalid digit '%c'%s", argv[1][i],
671                                         VTY_NEWLINE);
672                                 return CMD_WARNING;
673                         }
674                 }
675                 mncc_call(ms, (char *)argv[1]);
676         }
677
678         return CMD_SUCCESS;
679 }
680
681 DEFUN(call_retr, call_retr_cmd, "call MS_NAME retrieve [number]",
682         "Make a call\nName of MS (see \"show ms\")\n"
683         "Retrieve call on hold\nNumber of call to retrieve")
684 {
685         struct osmocom_ms *ms;
686
687         ms = get_ms(argv[0], vty);
688         if (!ms)
689                 return CMD_WARNING;
690
691         mncc_retrieve(ms, (argc > 1) ? atoi(argv[1]) : 0);
692
693         return CMD_SUCCESS;
694 }
695
696 DEFUN(network_show, network_show_cmd, "network show MS_NAME",
697         "Network ...\nShow results of network search (again)\n"
698         "Name of MS (see \"show ms\")")
699 {
700         struct osmocom_ms *ms;
701         struct gsm_settings *set;
702         struct gsm322_plmn *plmn;
703         struct gsm322_plmn_list *temp;
704
705         ms = get_ms(argv[0], vty);
706         if (!ms)
707                 return CMD_WARNING;
708         set = &ms->settings;
709         plmn = &ms->plmn;
710
711         if (set->plmn_mode != PLMN_MODE_AUTO
712          && plmn->state != GSM322_M3_NOT_ON_PLMN) {
713                 vty_out(vty, "Start network search first!%s", VTY_NEWLINE);
714                 return CMD_WARNING;
715         }
716
717         llist_for_each_entry(temp, &plmn->sorted_plmn, entry)
718                 vty_out(vty, " Network %s, %s (%s, %s)%s",
719                         gsm_print_mcc(temp->mcc), gsm_print_mnc(temp->mnc),
720                         gsm_get_mcc(temp->mcc),
721                         gsm_get_mnc(temp->mcc, temp->mnc), VTY_NEWLINE);
722
723         return CMD_SUCCESS;
724 }
725
726 DEFUN(network_search, network_search_cmd, "network search MS_NAME",
727         "Network ...\nTrigger network search\nName of MS (see \"show ms\")")
728 {
729         struct osmocom_ms *ms;
730         struct msgb *nmsg;
731
732         ms = get_ms(argv[0], vty);
733         if (!ms)
734                 return CMD_WARNING;
735
736         nmsg = gsm322_msgb_alloc(GSM322_EVENT_USER_RESEL);
737         if (!nmsg)
738                 return CMD_WARNING;
739         gsm322_plmn_sendmsg(ms, nmsg);
740
741         return CMD_SUCCESS;
742 }
743
744 DEFUN(cfg_gps_enable, cfg_gps_enable_cmd, "gps enable",
745         "GPS receiver")
746 {
747         if (gps_open()) {
748                 gps.enable = 1;
749                 vty_out(vty, "Failed to open GPS device!%s", VTY_NEWLINE);
750                 return CMD_WARNING;
751         }
752         gps.enable = 1;
753
754         return CMD_SUCCESS;
755 }
756
757 DEFUN(cfg_no_gps_enable, cfg_no_gps_enable_cmd, "no gps enable",
758         NO_STR "Disable GPS receiver")
759 {
760         if (gps.enable)
761                 gps_close();
762         gps.enable = 0;
763
764         return CMD_SUCCESS;
765 }
766
767 DEFUN(cfg_gps_device, cfg_gps_device_cmd, "gps device DEVICE",
768         "GPS receiver\nSelect serial device\n"
769         "Full path of serial device including /dev/")
770 {
771         strncpy(gps.device, argv[0], sizeof(gps.device));
772         gps.device[sizeof(gps.device) - 1] = '\0';
773         if (gps.enable) {
774                 gps_close();
775                 if (gps_open()) {
776                         vty_out(vty, "Failed to open GPS device!%s",
777                                 VTY_NEWLINE);
778                         return CMD_WARNING;
779                 }
780         }
781
782         return CMD_SUCCESS;
783 }
784
785 DEFUN(cfg_gps_baud, cfg_gps_baud_cmd, "gps baudrate "
786         "(default|4800|""9600|19200|38400|57600|115200)",
787         "GPS receiver\nSelect baud rate\nDefault, don't modify\n\n\n\n\n\n")
788 {
789         if (argv[0][0] == 'd')
790                 gps.baud = 0;
791         else
792                 gps.baud = atoi(argv[0]);
793         if (gps.enable) {
794                 gps_close();
795                 if (gps_open()) {
796                         gps.enable = 0;
797                         vty_out(vty, "Failed to open GPS device!%s",
798                                 VTY_NEWLINE);
799                         return CMD_WARNING;
800                 }
801         }
802
803         return CMD_SUCCESS;
804 }
805
806 /* per MS config */
807 DEFUN(cfg_ms, cfg_ms_cmd, "ms MS_NAME",
808         "Select a mobile station to configure\nName of MS (see \"show ms\")")
809 {
810         struct osmocom_ms *ms;
811
812         ms = get_ms(argv[0], vty);
813         if (!ms)
814                 return CMD_WARNING;
815
816         vty->index = ms;
817         vty->node = MS_NODE;
818
819         return CMD_SUCCESS;
820 }
821
822 #define SUP_WRITE(item, cmd) \
823         if (sup->item) \
824                 vty_out(vty, "  %s%s%s", (set->item) ? "" : "no ", cmd, \
825                         VTY_NEWLINE);
826
827 static void config_write_ms_single(struct vty *vty, struct osmocom_ms *ms)
828 {
829         struct gsm_settings *set = &ms->settings;
830         struct gsm_support *sup = &ms->support;
831
832         vty_out(vty, "ms %s%s", ms->name, VTY_NEWLINE);
833         switch(set->sim_type) {
834                 case GSM_SIM_TYPE_NONE:
835                 vty_out(vty, " sim none%s", VTY_NEWLINE);
836                 break;
837                 case GSM_SIM_TYPE_READER:
838                 vty_out(vty, " sim reader%s", VTY_NEWLINE);
839                 break;
840                 case GSM_SIM_TYPE_TEST:
841                 vty_out(vty, " sim test%s", VTY_NEWLINE);
842                 break;
843         }
844         vty_out(vty, " network-selection-mode %s%s", (set->plmn_mode
845                         == PLMN_MODE_AUTO) ? "auto" : "manual", VTY_NEWLINE);
846         vty_out(vty, " imei %s %s%s", set->imei,
847                 set->imeisv + strlen(set->imei), VTY_NEWLINE);
848         if (set->imei_random)
849                 vty_out(vty, " imei-random %d%s", set->imei_random,
850                         VTY_NEWLINE);
851         else
852                 vty_out(vty, " imei-fixed%s", VTY_NEWLINE);
853         if (set->emergency_imsi[0])
854                 vty_out(vty, " emergency-imsi %s%s", set->emergency_imsi,
855                         VTY_NEWLINE);
856         else
857                 vty_out(vty, " no emergency-imsi%s", VTY_NEWLINE);
858         vty_out(vty, " %scall-waiting%s", (set->cw) ? "" : "no ", VTY_NEWLINE);
859         vty_out(vty, " %sclip%s", (set->clip) ? "" : "no ", VTY_NEWLINE);
860         vty_out(vty, " %sclir%s", (set->clir) ? "" : "no ", VTY_NEWLINE);
861         if (set->alter_tx_power)
862                 if (set->alter_tx_power_value)
863                         vty_out(vty, " tx-power %d%s",
864                                 set->alter_tx_power_value, VTY_NEWLINE);
865                 else
866                         vty_out(vty, " tx-power full%s", VTY_NEWLINE);
867         else
868                 vty_out(vty, " tx-power auto%s", VTY_NEWLINE);
869         if (set->alter_delay)
870                 vty_out(vty, " simulated-delay %d%s", set->alter_delay,
871                         VTY_NEWLINE);
872         else
873                 vty_out(vty, " no simulated-delay%s", VTY_NEWLINE);
874         if (set->stick)
875                 vty_out(vty, " stick %d%s", set->stick_arfcn,
876                         VTY_NEWLINE);
877         else
878                 vty_out(vty, " no stick%s", VTY_NEWLINE);
879         if (set->no_lupd)
880                 vty_out(vty, " no location-updating%s", VTY_NEWLINE);
881         else
882                 vty_out(vty, " location-updating%s", VTY_NEWLINE);
883         if (set->full_v1 || set->full_v2 || set->full_v3) {
884                 /* mandatory anyway */
885                 vty_out(vty, " codec full-speed%s%s",
886                         (!set->half_prefer) ? " prefer" : "",
887                         VTY_NEWLINE);
888         }
889         if (set->half_v1 || set->half_v3) {
890                 if (set->half)
891                         vty_out(vty, " codec half-speed%s%s",
892                                 (set->half_prefer) ? " prefer" : "",
893                                 VTY_NEWLINE);
894                 else
895                         vty_out(vty, " no codec half-speed%s", VTY_NEWLINE);
896         }
897         vty_out(vty, " support%s", VTY_NEWLINE);
898         SUP_WRITE(sms_ptp, "sms");
899         SUP_WRITE(a5_1, "a5/1");
900         SUP_WRITE(a5_2, "a5/2");
901         SUP_WRITE(a5_3, "a5/3");
902         SUP_WRITE(a5_4, "a5/4");
903         SUP_WRITE(a5_5, "a5/5");
904         SUP_WRITE(a5_6, "a5/6");
905         SUP_WRITE(a5_7, "a5/7");
906         SUP_WRITE(p_gsm, "p-gsm");
907         SUP_WRITE(e_gsm, "e-gsm");
908         SUP_WRITE(r_gsm, "r-gsm");
909         SUP_WRITE(dcs, "dcs");
910         vty_out(vty, "  class-900 %d%s", set->class_900, VTY_NEWLINE);
911         vty_out(vty, "  class-dcs %d%s", set->class_dcs, VTY_NEWLINE);
912         switch (set->ch_cap) {
913         case GSM_CAP_SDCCH:
914                 vty_out(vty, "  channel-capability sdcch%s", VTY_NEWLINE);
915                 break;
916         case GSM_CAP_SDCCH_TCHF:
917                 vty_out(vty, "  channel-capability sdcch+tchf%s", VTY_NEWLINE);
918                 break;
919         case GSM_CAP_SDCCH_TCHF_TCHH:
920                 vty_out(vty, "  channel-capability sdcch+tchf+tchh%s",
921                         VTY_NEWLINE);
922                 break;
923         }
924         SUP_WRITE(full_v1, "full-speech-v1");
925         SUP_WRITE(full_v2, "full-speech-v2");
926         SUP_WRITE(full_v3, "full-speech-v3");
927         SUP_WRITE(half_v1, "half-speech-v1");
928         SUP_WRITE(half_v3, "half-speech-v3");
929         vty_out(vty, "  min-rxlev %d%s", set->min_rxlev_db, VTY_NEWLINE);
930         vty_out(vty, "  dsc-max %d%s", set->dsc_max, VTY_NEWLINE);
931         vty_out(vty, " exit%s", VTY_NEWLINE);
932         vty_out(vty, " test-sim%s", VTY_NEWLINE);
933         vty_out(vty, "  imsi %s%s", set->test_imsi, VTY_NEWLINE);
934         switch (set->test_ki_type) {
935         case GSM_SIM_KEY_XOR:
936                 vty_out(vty, "  ki xor %s%s", hexdump(set->test_ki, 12),
937                         VTY_NEWLINE);
938                 break;
939         case GSM_SIM_KEY_COMP128:
940                 vty_out(vty, "  ki comp128 %s%s", hexdump(set->test_ki, 16),
941                         VTY_NEWLINE);
942                 break;
943         }
944         vty_out(vty, "  %sbarred-access%s", (set->test_barr) ? "" : "no ",
945                 VTY_NEWLINE);
946         if (set->test_rplmn_valid)
947                 vty_out(vty, "  rplmn %s %s%s",
948                         gsm_print_mcc(set->test_rplmn_mcc),
949                         gsm_print_mnc(set->test_rplmn_mnc),
950                         VTY_NEWLINE);
951         else
952                 vty_out(vty, "  no rplmn%s", VTY_NEWLINE);
953         vty_out(vty, "  hplmn-search %s%s", (set->test_always) ? "everywhere"
954                         : "foreign-country", VTY_NEWLINE);
955         vty_out(vty, " exit%s", VTY_NEWLINE);
956         vty_out(vty, "exit%s", VTY_NEWLINE);
957         vty_out(vty, "!%s", VTY_NEWLINE);
958 }
959
960 static int config_write_ms(struct vty *vty)
961 {
962         struct osmocom_ms *ms;
963
964         vty_out(vty, "gps device %s%s", gps.device, VTY_NEWLINE);
965         if (gps.baud)
966                 vty_out(vty, "gps baudrate %d%s", gps.baud, VTY_NEWLINE);
967         else
968                 vty_out(vty, "gps baudrate default%s", VTY_NEWLINE);
969         vty_out(vty, "%sgps enable%s", (gps.enable) ? "" : "no ", VTY_NEWLINE);
970         vty_out(vty, "!%s", VTY_NEWLINE);
971
972         llist_for_each_entry(ms, &ms_list, entity)
973                 config_write_ms_single(vty, ms);
974
975         return CMD_SUCCESS;
976 }
977
978 DEFUN(cfg_ms_sim, cfg_ms_sim_cmd, "sim (none|reader|test)",
979         "Set SIM card type when powering on\nNo SIM interted\n"
980         "Use SIM from reader\nTest SIM inserted")
981 {
982         struct osmocom_ms *ms = vty->index;
983         struct gsm_settings *set = &ms->settings;
984
985         switch (argv[0][0]) {
986         case 'n':
987                 set->sim_type = GSM_SIM_TYPE_NONE;
988                 break;
989         case 'r':
990                 set->sim_type = GSM_SIM_TYPE_READER;
991                 break;
992         case 't':
993                 set->sim_type = GSM_SIM_TYPE_TEST;
994                 break;
995         default:
996                 vty_out(vty, "unknown SIM type%s", VTY_NEWLINE);
997                 return CMD_WARNING;
998         }
999
1000         vty_restart(vty);
1001         return CMD_SUCCESS;
1002 }
1003
1004 DEFUN(cfg_ms_mode, cfg_ms_mode_cmd, "network-selection-mode (auto|manual)",
1005         "Set network selection mode\nAutomatic network selection\n"
1006         "Manual network selection")
1007 {
1008         struct osmocom_ms *ms = vty->index;
1009         struct gsm_settings *set = &ms->settings;
1010         struct msgb *nmsg;
1011
1012         if (!ms->plmn.state) {
1013                 if (argv[0][0] == 'a')
1014                         set->plmn_mode = PLMN_MODE_AUTO;
1015                 else
1016                         set->plmn_mode = PLMN_MODE_MANUAL;
1017
1018                 return CMD_SUCCESS;
1019         }
1020         if (argv[0][0] == 'a')
1021                 nmsg = gsm322_msgb_alloc(GSM322_EVENT_SEL_AUTO);
1022         else
1023                 nmsg = gsm322_msgb_alloc(GSM322_EVENT_SEL_MANUAL);
1024         if (!nmsg)
1025                 return CMD_WARNING;
1026         gsm322_plmn_sendmsg(ms, nmsg);
1027
1028         return CMD_SUCCESS;
1029 }
1030
1031 DEFUN(cfg_ms_imei, cfg_ms_imei_cmd, "imei IMEI [SV]",
1032         "Set IMEI (enter without control digit)\n15 Digits IMEI\n"
1033         "Software version digit")
1034 {
1035         struct osmocom_ms *ms = vty->index;
1036         struct gsm_settings *set = &ms->settings;
1037         char *error, *sv = "0";
1038
1039         if (argc >= 2)
1040                 sv = (char *)argv[1];
1041
1042         error = gsm_check_imei(argv[0], sv);
1043         if (error) {
1044                 vty_out(vty, "%s%s", error, VTY_NEWLINE);
1045                 return CMD_WARNING;
1046         }
1047
1048         strcpy(set->imei, argv[0]);
1049         strcpy(set->imeisv, argv[0]);
1050         strcpy(set->imeisv + 15, sv);
1051
1052         return CMD_SUCCESS;
1053 }
1054
1055 DEFUN(cfg_ms_imei_fixed, cfg_ms_imei_fixed_cmd, "imei-fixed",
1056         "Use fixed IMEI on every power on")
1057 {
1058         struct osmocom_ms *ms = vty->index;
1059         struct gsm_settings *set = &ms->settings;
1060
1061         set->imei_random = 0;
1062
1063         vty_restart(vty);
1064         return CMD_SUCCESS;
1065 }
1066
1067 DEFUN(cfg_ms_imei_random, cfg_ms_imei_random_cmd, "imei-random <0-15>",
1068         "Use random IMEI on every power on\n"
1069         "Number of trailing digits to randomize")
1070 {
1071         struct osmocom_ms *ms = vty->index;
1072         struct gsm_settings *set = &ms->settings;
1073
1074         set->imei_random = atoi(argv[0]);
1075
1076         vty_restart(vty);
1077         return CMD_SUCCESS;
1078 }
1079
1080 DEFUN(cfg_ms_emerg_imsi, cfg_ms_emerg_imsi_cmd, "emergency-imsi IMSI",
1081         "Use special IMSI for emergency calls\n15 digits IMSI")
1082 {
1083         struct osmocom_ms *ms = vty->index;
1084         struct gsm_settings *set = &ms->settings;
1085         char *error;
1086
1087         error = gsm_check_imsi(argv[0]);
1088         if (error) {
1089                 vty_out(vty, "%s%s", error, VTY_NEWLINE);
1090                 return CMD_WARNING;
1091         }
1092         strcpy(set->emergency_imsi, argv[0]);
1093
1094         return CMD_SUCCESS;
1095 }
1096
1097 DEFUN(cfg_ms_no_emerg_imsi, cfg_ms_no_emerg_imsi_cmd, "no emergency-imsi",
1098         NO_STR "Use IMSI of SIM or IMEI for emergency calls")
1099 {
1100         struct osmocom_ms *ms = vty->index;
1101         struct gsm_settings *set = &ms->settings;
1102
1103         set->emergency_imsi[0] = '\0';
1104
1105         return CMD_SUCCESS;
1106 }
1107
1108 DEFUN(cfg_no_cw, cfg_ms_no_cw_cmd, "no call-waiting",
1109         NO_STR "Disallow waiting calls")
1110 {
1111         struct osmocom_ms *ms = vty->index;
1112         struct gsm_settings *set = &ms->settings;
1113
1114         set->cw = 0;
1115
1116         return CMD_SUCCESS;
1117 }
1118
1119 DEFUN(cfg_cw, cfg_ms_cw_cmd, "call-waiting",
1120         "Allow waiting calls")
1121 {
1122         struct osmocom_ms *ms = vty->index;
1123         struct gsm_settings *set = &ms->settings;
1124
1125         set->cw = 1;
1126
1127         return CMD_SUCCESS;
1128 }
1129
1130 DEFUN(cfg_clip, cfg_ms_clip_cmd, "clip",
1131         "Force caller ID presentation")
1132 {
1133         struct osmocom_ms *ms = vty->index;
1134         struct gsm_settings *set = &ms->settings;
1135
1136         set->clip = 1;
1137         set->clir = 0;
1138
1139         return CMD_SUCCESS;
1140 }
1141
1142 DEFUN(cfg_clir, cfg_ms_clir_cmd, "clir",
1143         "Force caller ID restriction")
1144 {
1145         struct osmocom_ms *ms = vty->index;
1146         struct gsm_settings *set = &ms->settings;
1147
1148         set->clip = 0;
1149         set->clir = 1;
1150
1151         return CMD_SUCCESS;
1152 }
1153
1154 DEFUN(cfg_no_clip, cfg_ms_no_clip_cmd, "no clip",
1155         NO_STR "Disable forcing of caller ID presentation")
1156 {
1157         struct osmocom_ms *ms = vty->index;
1158         struct gsm_settings *set = &ms->settings;
1159
1160         set->clip = 0;
1161
1162         return CMD_SUCCESS;
1163 }
1164
1165 DEFUN(cfg_no_clir, cfg_ms_no_clir_cmd, "no clir",
1166         NO_STR "Disable forcing of caller ID restriction")
1167 {
1168         struct osmocom_ms *ms = vty->index;
1169         struct gsm_settings *set = &ms->settings;
1170
1171         set->clir = 0;
1172
1173         return CMD_SUCCESS;
1174 }
1175
1176 DEFUN(cfg_ms_tx_power, cfg_ms_tx_power_cmd, "tx-power (auto|full)",
1177         "Set the way to choose transmit power\nControlled by BTS\n"
1178         "Always full power\nFixed GSM power value if supported")
1179 {
1180         struct osmocom_ms *ms = vty->index;
1181         struct gsm_settings *set = &ms->settings;
1182
1183         switch (argv[0][0]) {
1184         case 'a':
1185                 set->alter_tx_power = 0;
1186                 break;
1187         case 'f':
1188                 set->alter_tx_power = 1;
1189                 set->alter_tx_power_value = 0;
1190                 break;
1191         }
1192
1193         return CMD_SUCCESS;
1194 }
1195
1196 DEFUN(cfg_ms_tx_power_val, cfg_ms_tx_power_val_cmd, "tx-power <0-31>",
1197         "Set the way to choose transmit power\n"
1198         "Fixed GSM power value if supported")
1199 {
1200         struct osmocom_ms *ms = vty->index;
1201         struct gsm_settings *set = &ms->settings;
1202
1203         set->alter_tx_power = 1;
1204         set->alter_tx_power_value = atoi(argv[0]);
1205
1206         return CMD_SUCCESS;
1207 }
1208
1209 DEFUN(cfg_ms_sim_delay, cfg_ms_sim_delay_cmd, "simulated-delay <-128-127>",
1210         "Simulate a lower or higher distance from the BTS\n"
1211         "Delay in half bits (distance in 553.85 meter steps)")
1212 {
1213         struct osmocom_ms *ms = vty->index;
1214         struct gsm_settings *set = &ms->settings;
1215
1216         set->alter_delay = atoi(argv[0]);
1217         gsm48_rr_alter_delay(ms);
1218
1219         return CMD_SUCCESS;
1220 }
1221
1222 DEFUN(cfg_ms_no_sim_delay, cfg_ms_no_sim_delay_cmd, "no simulated-delay",
1223         NO_STR "Do not simulate a lower or higher distance from the BTS")
1224 {
1225         struct osmocom_ms *ms = vty->index;
1226         struct gsm_settings *set = &ms->settings;
1227
1228         set->alter_delay = 0;
1229         gsm48_rr_alter_delay(ms);
1230
1231         return CMD_SUCCESS;
1232 }
1233
1234 DEFUN(cfg_ms_stick, cfg_ms_stick_cmd, "stick <0-1023>",
1235         "Stick to the given cell\nARFCN of the cell to stick to")
1236 {
1237         struct osmocom_ms *ms = vty->index;
1238         struct gsm_settings *set = &ms->settings;
1239
1240         set->stick = 1;
1241         set->stick_arfcn = atoi(argv[0]);
1242
1243         return CMD_SUCCESS;
1244 }
1245
1246 DEFUN(cfg_ms_no_stick, cfg_ms_no_stick_cmd, "no stick",
1247         NO_STR "Do not stick to any cell")
1248 {
1249         struct osmocom_ms *ms = vty->index;
1250         struct gsm_settings *set = &ms->settings;
1251
1252         set->stick = 0;
1253
1254         return CMD_SUCCESS;
1255 }
1256
1257 DEFUN(cfg_ms_lupd, cfg_ms_lupd_cmd, "location-updating",
1258         "Allow location updating")
1259 {
1260         struct osmocom_ms *ms = vty->index;
1261         struct gsm_settings *set = &ms->settings;
1262
1263         set->no_lupd = 0;
1264
1265         return CMD_SUCCESS;
1266 }
1267
1268 DEFUN(cfg_ms_no_lupd, cfg_ms_no_lupd_cmd, "no location-updating",
1269         NO_STR "Do not allow location updating")
1270 {
1271         struct osmocom_ms *ms = vty->index;
1272         struct gsm_settings *set = &ms->settings;
1273
1274         set->no_lupd = 1;
1275
1276         return CMD_SUCCESS;
1277 }
1278
1279 DEFUN(cfg_codec_full, cfg_ms_codec_full_cmd, "codec full-speed",
1280         "Enable codec\nFull speed speech codec")
1281 {
1282         struct osmocom_ms *ms = vty->index;
1283         struct gsm_settings *set = &ms->settings;
1284
1285         if (!set->full_v1 && !set->full_v2 && !set->full_v3) {
1286                 vty_out(vty, "Full-rate codec not supported%s", VTY_NEWLINE);
1287                 return CMD_WARNING;
1288         }
1289
1290         return CMD_SUCCESS;
1291 }
1292
1293 DEFUN(cfg_codec_full_pref, cfg_ms_codec_full_pref_cmd, "codec full-speed "
1294         "prefer",
1295         "Enable codec\nFull speed speech codec\nPrefer this codec")
1296 {
1297         struct osmocom_ms *ms = vty->index;
1298         struct gsm_settings *set = &ms->settings;
1299
1300         if (!set->full_v1 && !set->full_v2 && !set->full_v3) {
1301                 vty_out(vty, "Full-rate codec not supported%s", VTY_NEWLINE);
1302                 return CMD_WARNING;
1303         }
1304
1305         set->half_prefer = 0;
1306
1307         return CMD_SUCCESS;
1308 }
1309
1310 DEFUN(cfg_codec_half, cfg_ms_codec_half_cmd, "codec half-speed",
1311         "Enable codec\nHalf speed speech codec")
1312 {
1313         struct osmocom_ms *ms = vty->index;
1314         struct gsm_settings *set = &ms->settings;
1315
1316         if (!set->half_v1 && !set->half_v3) {
1317                 vty_out(vty, "Half-rate codec not supported%s", VTY_NEWLINE);
1318                 return CMD_WARNING;
1319         }
1320
1321         set->half = 1;
1322
1323         return CMD_SUCCESS;
1324 }
1325
1326 DEFUN(cfg_codec_half_pref, cfg_ms_codec_half_pref_cmd, "codec half-speed "
1327         "prefer",
1328         "Enable codec\nHalf speed speech codec\nPrefer this codec")
1329 {
1330         struct osmocom_ms *ms = vty->index;
1331         struct gsm_settings *set = &ms->settings;
1332
1333         if (!set->half_v1 && !set->half_v3) {
1334                 vty_out(vty, "Half-rate codec not supported%s", VTY_NEWLINE);
1335                 return CMD_WARNING;
1336         }
1337
1338         set->half = 1;
1339         set->half_prefer = 1;
1340
1341         return CMD_SUCCESS;
1342 }
1343
1344 DEFUN(cfg_no_codec_half, cfg_ms_no_codec_half_cmd, "no codec half-speed",
1345         NO_STR "Disable codec\nHalf speed speech codec")
1346 {
1347         struct osmocom_ms *ms = vty->index;
1348         struct gsm_settings *set = &ms->settings;
1349
1350         if (!set->half_v1 && !set->half_v3) {
1351                 vty_out(vty, "Half-rate codec not supported%s", VTY_NEWLINE);
1352                 return CMD_WARNING;
1353         }
1354
1355         set->half = 0;
1356         set->half_prefer = 0;
1357
1358         return CMD_SUCCESS;
1359 }
1360
1361 static int config_write_dummy(struct vty *vty)
1362 {
1363         return CMD_SUCCESS;
1364 }
1365
1366 /* per support config */
1367 DEFUN(cfg_ms_support, cfg_ms_support_cmd, "support",
1368         "Define supported features")
1369 {
1370         vty->node = SUPPORT_NODE;
1371
1372         return CMD_SUCCESS;
1373 }
1374
1375 #define SUP_EN(cfg, cfg_cmd, item, cmd, desc, restart) \
1376 DEFUN(cfg, cfg_cmd, cmd, "Enable " desc "support") \
1377 { \
1378         struct osmocom_ms *ms = vty->index; \
1379         struct gsm_settings *set = &ms->settings; \
1380         struct gsm_support *sup = &ms->support; \
1381         if (!sup->item) { \
1382                 vty_out(vty, desc " not supported%s", VTY_NEWLINE); \
1383                 if (vty_reading) \
1384                         return CMD_SUCCESS; \
1385                 return CMD_WARNING; \
1386         } \
1387         if (restart) \
1388                 vty_restart(vty); \
1389         set->item = 1; \
1390         return CMD_SUCCESS; \
1391 }
1392
1393 #define SUP_DI(cfg, cfg_cmd, item, cmd, desc, restart) \
1394 DEFUN(cfg, cfg_cmd, "no " cmd, NO_STR "Disable " desc " support") \
1395 { \
1396         struct osmocom_ms *ms = vty->index; \
1397         struct gsm_settings *set = &ms->settings; \
1398         struct gsm_support *sup = &ms->support; \
1399         if (!sup->item) { \
1400                 vty_out(vty, desc " not supported%s", VTY_NEWLINE); \
1401                 if (vty_reading) \
1402                         return CMD_SUCCESS; \
1403                 return CMD_WARNING; \
1404         } \
1405         if (restart) \
1406                 vty_restart(vty); \
1407         set->item = 0; \
1408         return CMD_SUCCESS; \
1409 }
1410
1411 SUP_EN(cfg_ms_sup_sms, cfg_ms_sup_sms_cmd, sms_ptp, "sms", "SMS", 0);
1412 SUP_DI(cfg_ms_sup_no_sms, cfg_ms_sup_no_sms_cmd, sms_ptp, "sms", "SMS", 0);
1413 SUP_EN(cfg_ms_sup_a5_1, cfg_ms_sup_a5_1_cmd, a5_1, "a5/1", "A5/1", 0);
1414 SUP_DI(cfg_ms_sup_no_a5_1, cfg_ms_sup_no_a5_1_cmd, a5_1, "a5/1", "A5/1", 0);
1415 SUP_EN(cfg_ms_sup_a5_2, cfg_ms_sup_a5_2_cmd, a5_2, "a5/2", "A5/2", 0);
1416 SUP_DI(cfg_ms_sup_no_a5_2, cfg_ms_sup_no_a5_2_cmd, a5_2, "a5/2", "A5/2", 0);
1417 SUP_EN(cfg_ms_sup_a5_3, cfg_ms_sup_a5_3_cmd, a5_3, "a5/3", "A5/3", 0);
1418 SUP_DI(cfg_ms_sup_no_a5_3, cfg_ms_sup_no_a5_3_cmd, a5_3, "a5/3", "A5/3", 0);
1419 SUP_EN(cfg_ms_sup_a5_4, cfg_ms_sup_a5_4_cmd, a5_4, "a5/4", "A5/4", 0);
1420 SUP_DI(cfg_ms_sup_no_a5_4, cfg_ms_sup_no_a5_4_cmd, a5_4, "a5/4", "A5/4", 0);
1421 SUP_EN(cfg_ms_sup_a5_5, cfg_ms_sup_a5_5_cmd, a5_5, "a5/5", "A5/5", 0);
1422 SUP_DI(cfg_ms_sup_no_a5_5, cfg_ms_sup_no_a5_5_cmd, a5_5, "a5/5", "A5/5", 0);
1423 SUP_EN(cfg_ms_sup_a5_6, cfg_ms_sup_a5_6_cmd, a5_6, "a5/6", "A5/6", 0);
1424 SUP_DI(cfg_ms_sup_no_a5_6, cfg_ms_sup_no_a5_6_cmd, a5_6, "a5/6", "A5/6", 0);
1425 SUP_EN(cfg_ms_sup_a5_7, cfg_ms_sup_a5_7_cmd, a5_7, "a5/7", "A5/7", 0);
1426 SUP_DI(cfg_ms_sup_no_a5_7, cfg_ms_sup_no_a5_7_cmd, a5_7, "a5/7", "A5/7", 1);
1427 SUP_EN(cfg_ms_sup_p_gsm, cfg_ms_sup_p_gsm_cmd, p_gsm, "p-gsm", "P-GSM (900)",
1428         1);
1429 SUP_DI(cfg_ms_sup_no_p_gsm, cfg_ms_sup_no_p_gsm_cmd, p_gsm, "p-gsm",
1430         "P-GSM (900)", 1);
1431 SUP_EN(cfg_ms_sup_e_gsm, cfg_ms_sup_e_gsm_cmd, e_gsm, "e-gsm", "E-GSM (850)",
1432         1);
1433 SUP_DI(cfg_ms_sup_no_e_gsm, cfg_ms_sup_no_e_gsm_cmd, e_gsm, "e-gsm",
1434         "E-GSM (850)", 1);
1435 SUP_EN(cfg_ms_sup_r_gsm, cfg_ms_sup_r_gsm_cmd, r_gsm, "r-gsm", "R-GSM (850)",
1436         1);
1437 SUP_DI(cfg_ms_sup_no_r_gsm, cfg_ms_sup_no_r_gsm_cmd, r_gsm, "r-gsm",
1438         "R-GSM (850)", 1);
1439 SUP_EN(cfg_ms_sup_dcs, cfg_ms_sup_dcs_cmd, dcs, "dcs", "DCS (1800)", 0);
1440 SUP_DI(cfg_ms_sup_no_dcs, cfg_ms_sup_no_dcs_cmd, dcs, "dcs", "DCS (1800)", 0);
1441
1442 DEFUN(cfg_ms_sup_class_900, cfg_ms_sup_class_900_cmd, "class-900 (1|2|3|4|5)",
1443         "Select power class for GSM 850/900\n"
1444         "20 Watts\n"
1445         "8 Watts\n"
1446         "5 Watts\n"
1447         "2 Watts\n"
1448         "0.8 Watts")
1449 {
1450         struct osmocom_ms *ms = vty->index;
1451         struct gsm_settings *set = &ms->settings;
1452         struct gsm_support *sup = &ms->support;
1453
1454         set->class_900 = atoi(argv[0]);
1455
1456         if (set->class_900 < sup->class_900 && !vty_reading)
1457                 vty_out(vty, "You selected an higher class than supported "
1458                         " by hardware!%s", VTY_NEWLINE);
1459
1460         return CMD_SUCCESS;
1461 }
1462
1463 DEFUN(cfg_ms_sup_class_dcs, cfg_ms_sup_class_dcs_cmd, "class-dcs (1|2|3)",
1464         "Select power class for DCS 1800\n"
1465         "1 Watt\n"
1466         "0.25 Watts\n"
1467         "4 Watts")
1468 {
1469         struct osmocom_ms *ms = vty->index;
1470         struct gsm_settings *set = &ms->settings;
1471         struct gsm_support *sup = &ms->support;
1472
1473         set->class_dcs = atoi(argv[0]);
1474
1475         if (((set->class_dcs + 1) & 3) < ((sup->class_dcs + 1) & 3)
1476          && !vty_reading)
1477                 vty_out(vty, "You selected an higher class than supported "
1478                         " by hardware!%s", VTY_NEWLINE);
1479
1480         return CMD_SUCCESS;
1481 }
1482
1483 DEFUN(cfg_ms_sup_ch_cap, cfg_ms_sup_ch_cap_cmd, "channel-capability "
1484         "(sdcch|sdcch+tchf|sdcch+tchf+tchh)",
1485         "Select channel capability\nSDCCH only\nSDCCH + TCH/F\nSDCCH + TCH/H")
1486 {
1487         struct osmocom_ms *ms = vty->index;
1488         struct gsm_settings *set = &ms->settings;
1489         struct gsm_support *sup = &ms->support;
1490         uint8_t ch_cap;
1491
1492         if (!strcmp(argv[0], "sdcch+tchf+tchh"))
1493                 ch_cap = GSM_CAP_SDCCH_TCHF_TCHH;
1494         else if (!strcmp(argv[0], "sdcch+tchf"))
1495                 ch_cap = GSM_CAP_SDCCH_TCHF;
1496         else
1497                 ch_cap = GSM_CAP_SDCCH;
1498
1499         if (ch_cap > sup->ch_cap && !vty_reading) {
1500                 vty_out(vty, "You selected an higher capability than supported "
1501                         " by hardware!%s", VTY_NEWLINE);
1502                 return CMD_WARNING;
1503         }
1504
1505         if (ch_cap != set->ch_cap
1506          && (ch_cap == GSM_CAP_SDCCH || set->ch_cap == GSM_CAP_SDCCH))
1507                 vty_restart(vty);
1508
1509         set->ch_cap = ch_cap;
1510
1511         return CMD_SUCCESS;
1512 }
1513
1514 SUP_EN(cfg_ms_sup_full_v1, cfg_ms_sup_full_v1_cmd, full_v1, "full-speech-v1",
1515         "Full rate speech V1", 0);
1516 SUP_DI(cfg_ms_sup_no_full_v1, cfg_ms_sup_no_full_v1_cmd, full_v1,
1517         "full-speech-v1", "Full rate speech V1", 0);
1518 SUP_EN(cfg_ms_sup_full_v2, cfg_ms_sup_full_v2_cmd, full_v2, "full-speech-v2",
1519         "Full rate speech V2 (EFR)", 0);
1520 SUP_DI(cfg_ms_sup_no_full_v2, cfg_ms_sup_no_full_v2_cmd, full_v2,
1521         "full-speech-v2", "Full rate speech V2 (EFR)", 0);
1522 SUP_EN(cfg_ms_sup_full_v3, cfg_ms_sup_full_v3_cmd, full_v3, "full-speech-v3",
1523         "Full rate speech V3 (AMR)", 0);
1524 SUP_DI(cfg_ms_sup_no_full_v3, cfg_ms_sup_no_full_v3_cmd, full_v3,
1525         "full-speech-v3", "Full rate speech V3 (AMR)", 0);
1526 SUP_EN(cfg_ms_sup_half_v1, cfg_ms_sup_half_v1_cmd, half_v1, "half-speech-v1",
1527         "Half rate speech V1 (AMR)", 0);
1528 SUP_DI(cfg_ms_sup_no_half_v1, cfg_ms_sup_no_half_v1_cmd, half_v1,
1529         "half-speech-v1", "Half rate speech V1", 0);
1530 SUP_EN(cfg_ms_sup_half_v3, cfg_ms_sup_half_v3_cmd, half_v3, "half-speech-v3",
1531         "Half rate speech V3 (AMR)", 0);
1532 SUP_DI(cfg_ms_sup_no_half_v3, cfg_ms_sup_no_half_v3_cmd, half_v3,
1533         "half-speech-v3", "Half rate speech V3", 0);
1534
1535 DEFUN(cfg_ms_sup_min_rxlev, cfg_ms_sup_min_rxlev_cmd, "min-rxlev <-110--47>",
1536         "Set the minimum receive level to select a cell\n"
1537         "Minimum receive level from -110 dBm to -47 dBm")
1538 {
1539         struct osmocom_ms *ms = vty->index;
1540         struct gsm_settings *set = &ms->settings;
1541
1542         set->min_rxlev_db = atoi(argv[0]);
1543
1544         return CMD_SUCCESS;
1545 }
1546
1547 DEFUN(cfg_ms_sup_dsc_max, cfg_ms_sup_dsc_max_cmd, "dsc-max <90-500>",
1548         "Set the maximum DSC value. Standard is 90. Increase to make mobile "
1549         "more reliable against bad RX signal. This increase the propability "
1550         "of missing a paging requests\n"
1551         "DSC initial and maximum value (standard is 90)")
1552 {
1553         struct osmocom_ms *ms = vty->index;
1554         struct gsm_settings *set = &ms->settings;
1555
1556         set->dsc_max = atoi(argv[0]);
1557
1558         return CMD_SUCCESS;
1559 }
1560
1561 /* per testsim config */
1562 DEFUN(cfg_ms_testsim, cfg_ms_testsim_cmd, "test-sim",
1563         "Configure test SIM emulation")
1564 {
1565         vty->node = TESTSIM_NODE;
1566
1567         return CMD_SUCCESS;
1568 }
1569
1570 DEFUN(cfg_test_imsi, cfg_test_imsi_cmd, "imsi IMSI",
1571         "Set IMSI on test card\n15 digits IMSI")
1572 {
1573         struct osmocom_ms *ms = vty->index;
1574         struct gsm_settings *set = &ms->settings;
1575         char *error = gsm_check_imsi(argv[0]);
1576
1577         if (error) {
1578                 vty_out(vty, "%s%s", error, VTY_NEWLINE);
1579                 return CMD_WARNING;
1580         }
1581
1582         strcpy(set->test_imsi, argv[0]);
1583
1584         vty_restart(vty);
1585         return CMD_SUCCESS;
1586 }
1587
1588 #define HEX_STR "\nByte as two digits hexadecimal"
1589 DEFUN(cfg_test_ki_xor, cfg_test_ki_xor_cmd, "ki xor HEX HEX HEX HEX HEX HEX "
1590         "HEX HEX HEX HEX HEX HEX",
1591         "Set Key (Kc) on test card\nUse XOR algorithm" HEX_STR HEX_STR HEX_STR
1592         HEX_STR HEX_STR HEX_STR HEX_STR HEX_STR HEX_STR HEX_STR HEX_STR HEX_STR)
1593 {
1594         struct osmocom_ms *ms = vty->index;
1595         struct gsm_settings *set = &ms->settings;
1596         uint8_t ki[12];
1597         const char *p;
1598         int i;
1599
1600         for (i = 0; i < 12; i++) {
1601                 p = argv[i];
1602                 if (!strncmp(p, "0x", 2))
1603                         p += 2;
1604                 if (strlen(p) != 2) {
1605                         vty_out(vty, "Expecting two digits hex value (with or "
1606                                 "without 0x in front)%s", VTY_NEWLINE);
1607                         return CMD_WARNING;
1608                 }
1609                 ki[i] = strtoul(p, NULL, 16);
1610         }
1611
1612         set->test_ki_type = GSM_SIM_KEY_XOR;
1613         memcpy(set->test_ki, ki, 12);
1614         return CMD_SUCCESS;
1615 }
1616
1617 DEFUN(cfg_test_ki_comp128, cfg_test_ki_comp128_cmd, "ki comp128 HEX HEX HEX "
1618         "HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX",
1619         "Set Key (Kc) on test card\nUse XOR algorithm" HEX_STR HEX_STR HEX_STR
1620         HEX_STR HEX_STR HEX_STR HEX_STR HEX_STR HEX_STR HEX_STR HEX_STR HEX_STR
1621         HEX_STR HEX_STR HEX_STR HEX_STR)
1622 {
1623         struct osmocom_ms *ms = vty->index;
1624         struct gsm_settings *set = &ms->settings;
1625         uint8_t ki[16];
1626         const char *p;
1627         int i;
1628
1629         for (i = 0; i < 16; i++) {
1630                 p = argv[i];
1631                 if (!strncmp(p, "0x", 2))
1632                         p += 2;
1633                 if (strlen(p) != 2) {
1634                         vty_out(vty, "Expecting two digits hex value (with or "
1635                                 "without 0x in front)%s", VTY_NEWLINE);
1636                         return CMD_WARNING;
1637                 }
1638                 ki[i] = strtoul(p, NULL, 16);
1639         }
1640
1641         set->test_ki_type = GSM_SIM_KEY_COMP128;
1642         memcpy(set->test_ki, ki, 16);
1643         return CMD_SUCCESS;
1644 }
1645
1646 DEFUN(cfg_test_barr, cfg_test_barr_cmd, "barred-access",
1647         "Allow access to barred cells")
1648 {
1649         struct osmocom_ms *ms = vty->index;
1650         struct gsm_settings *set = &ms->settings;
1651
1652         set->test_barr = 1;
1653
1654         return CMD_SUCCESS;
1655 }
1656
1657 DEFUN(cfg_test_no_barr, cfg_test_no_barr_cmd, "no barred-access",
1658         NO_STR "Deny access to barred cells")
1659 {
1660         struct osmocom_ms *ms = vty->index;
1661         struct gsm_settings *set = &ms->settings;
1662
1663         set->test_barr = 0;
1664
1665         return CMD_SUCCESS;
1666 }
1667
1668 DEFUN(cfg_test_no_rplmn, cfg_test_no_rplmn_cmd, "no rplmn",
1669         NO_STR "Unset Registered PLMN")
1670 {
1671         struct osmocom_ms *ms = vty->index;
1672         struct gsm_settings *set = &ms->settings;
1673
1674         set->test_rplmn_valid = 0;
1675
1676         vty_restart(vty);
1677         return CMD_SUCCESS;
1678 }
1679
1680 DEFUN(cfg_test_rplmn, cfg_test_rplmn_cmd, "rplmn MCC MNC",
1681         "Set Registered PLMN\nMobile Country Code\nMobile Network Code")
1682 {
1683         struct osmocom_ms *ms = vty->index;
1684         struct gsm_settings *set = &ms->settings;
1685         uint16_t mcc = gsm_input_mcc((char *)argv[0]),
1686                  mnc = gsm_input_mnc((char *)argv[1]);
1687
1688         if (!mcc) {
1689                 vty_out(vty, "Given MCC invalid%s", VTY_NEWLINE);
1690                 return CMD_WARNING;
1691         }
1692         if (!mnc) {
1693                 vty_out(vty, "Given MNC invalid%s", VTY_NEWLINE);
1694                 return CMD_WARNING;
1695         }
1696         set->test_rplmn_valid = 1;
1697         set->test_rplmn_mcc = mcc;
1698         set->test_rplmn_mnc = mnc;
1699
1700         vty_restart(vty);
1701         return CMD_SUCCESS;
1702 }
1703
1704 DEFUN(cfg_test_hplmn, cfg_test_hplmn_cmd, "hplmn-search (everywhere|foreign-country)",
1705         "Set Home PLMN search mode\n"
1706         "Search for HPLMN when on any other network\n"
1707         "Search for HPLMN when in a different country")
1708 {
1709         struct osmocom_ms *ms = vty->index;
1710         struct gsm_settings *set = &ms->settings;
1711
1712         switch (argv[0][0]) {
1713         case 'e':
1714                 set->test_always = 1;
1715                 break;
1716         case 'f':
1717                 set->test_always = 0;
1718                 break;
1719         }
1720
1721         vty_restart(vty);
1722         return CMD_SUCCESS;
1723 }
1724
1725 enum node_type ms_vty_go_parent(struct vty *vty)
1726 {
1727         switch (vty->node) {
1728         case MS_NODE:
1729                 vty->node = CONFIG_NODE;
1730                 vty->index = NULL;
1731                 break;
1732         case TESTSIM_NODE:
1733         case SUPPORT_NODE:
1734                 vty->node = MS_NODE;
1735                 break;
1736         default:
1737                 vty->node = CONFIG_NODE;
1738         }
1739
1740         return vty->node;
1741 }
1742
1743 /* Down vty node level. */
1744 gDEFUN(ournode_exit,
1745        ournode_exit_cmd, "exit", "Exit current mode and down to previous mode\n")
1746 {
1747         switch (vty->node) {
1748         case MS_NODE:
1749                 vty->node = CONFIG_NODE;
1750                 vty->index = NULL;
1751                 break;
1752         case TESTSIM_NODE:
1753         case SUPPORT_NODE:
1754                 vty->node = MS_NODE;
1755                 break;
1756         default:
1757                 break;
1758         }
1759         return CMD_SUCCESS;
1760 }
1761
1762 /* End of configuration. */
1763 gDEFUN(ournode_end,
1764        ournode_end_cmd, "end", "End current mode and change to enable mode.")
1765 {
1766         switch (vty->node) {
1767         case VIEW_NODE:
1768         case ENABLE_NODE:
1769                 /* Nothing to do. */
1770                 break;
1771         case CONFIG_NODE:
1772         case VTY_NODE:
1773         case MS_NODE:
1774         case TESTSIM_NODE:
1775         case SUPPORT_NODE:
1776                 vty_config_unlock(vty);
1777                 vty->node = ENABLE_NODE;
1778                 vty->index = NULL;
1779                 vty->index_sub = NULL;
1780                 break;
1781         default:
1782                 break;
1783         }
1784         return CMD_SUCCESS;
1785 }
1786
1787 #define SUP_NODE(item) \
1788         install_element(SUPPORT_NODE, &cfg_ms_sup_item_cmd);
1789
1790 int ms_vty_init(void)
1791 {
1792         install_element_ve(&show_ms_cmd);
1793         install_element_ve(&show_subscr_cmd);
1794         install_element_ve(&show_support_cmd);
1795         install_element_ve(&show_states_cmd);
1796         install_element_ve(&show_cell_cmd);
1797         install_element_ve(&show_cell_si_cmd);
1798         install_element_ve(&show_ba_cmd);
1799         install_element_ve(&show_forb_la_cmd);
1800         install_element_ve(&show_forb_plmn_cmd);
1801         install_element_ve(&monitor_network_cmd);
1802         install_element_ve(&no_monitor_network_cmd);
1803
1804         install_element(ENABLE_NODE, &sim_test_cmd);
1805         install_element(ENABLE_NODE, &sim_reader_cmd);
1806         install_element(ENABLE_NODE, &sim_remove_cmd);
1807         install_element(ENABLE_NODE, &sim_pin_cmd);
1808         install_element(ENABLE_NODE, &sim_disable_pin_cmd);
1809         install_element(ENABLE_NODE, &sim_enable_pin_cmd);
1810         install_element(ENABLE_NODE, &sim_change_pin_cmd);
1811         install_element(ENABLE_NODE, &sim_unblock_pin_cmd);
1812         install_element(ENABLE_NODE, &sim_lai_cmd);
1813         install_element(ENABLE_NODE, &network_search_cmd);
1814         install_element(ENABLE_NODE, &network_show_cmd);
1815         install_element(ENABLE_NODE, &network_select_cmd);
1816         install_element(ENABLE_NODE, &call_cmd);
1817         install_element(ENABLE_NODE, &call_retr_cmd);
1818
1819         install_element(CONFIG_NODE, &cfg_gps_device_cmd);
1820         install_element(CONFIG_NODE, &cfg_gps_baud_cmd);
1821         install_element(CONFIG_NODE, &cfg_gps_enable_cmd);
1822         install_element(CONFIG_NODE, &cfg_no_gps_enable_cmd);
1823
1824         install_element(CONFIG_NODE, &cfg_ms_cmd);
1825         install_element(CONFIG_NODE, &ournode_end_cmd);
1826         install_node(&ms_node, config_write_ms);
1827         install_default(MS_NODE);
1828         install_element(MS_NODE, &ournode_exit_cmd);
1829         install_element(MS_NODE, &ournode_end_cmd);
1830         install_element(MS_NODE, &cfg_ms_sim_cmd);
1831         install_element(MS_NODE, &cfg_ms_mode_cmd);
1832         install_element(MS_NODE, &cfg_ms_imei_cmd);
1833         install_element(MS_NODE, &cfg_ms_imei_fixed_cmd);
1834         install_element(MS_NODE, &cfg_ms_imei_random_cmd);
1835         install_element(MS_NODE, &cfg_ms_no_emerg_imsi_cmd);
1836         install_element(MS_NODE, &cfg_ms_emerg_imsi_cmd);
1837         install_element(MS_NODE, &cfg_ms_cw_cmd);
1838         install_element(MS_NODE, &cfg_ms_no_cw_cmd);
1839         install_element(MS_NODE, &cfg_ms_clip_cmd);
1840         install_element(MS_NODE, &cfg_ms_clir_cmd);
1841         install_element(MS_NODE, &cfg_ms_no_clip_cmd);
1842         install_element(MS_NODE, &cfg_ms_no_clir_cmd);
1843         install_element(MS_NODE, &cfg_ms_tx_power_cmd);
1844         install_element(MS_NODE, &cfg_ms_tx_power_val_cmd);
1845         install_element(MS_NODE, &cfg_ms_sim_delay_cmd);
1846         install_element(MS_NODE, &cfg_ms_no_sim_delay_cmd);
1847         install_element(MS_NODE, &cfg_ms_stick_cmd);
1848         install_element(MS_NODE, &cfg_ms_no_stick_cmd);
1849         install_element(MS_NODE, &cfg_ms_lupd_cmd);
1850         install_element(MS_NODE, &cfg_ms_no_lupd_cmd);
1851         install_element(MS_NODE, &cfg_ms_codec_full_cmd);
1852         install_element(MS_NODE, &cfg_ms_codec_full_pref_cmd);
1853         install_element(MS_NODE, &cfg_ms_codec_half_cmd);
1854         install_element(MS_NODE, &cfg_ms_codec_half_pref_cmd);
1855         install_element(MS_NODE, &cfg_ms_no_codec_half_cmd);
1856         install_element(MS_NODE, &cfg_ms_testsim_cmd);
1857         install_element(MS_NODE, &cfg_ms_support_cmd);
1858         install_node(&support_node, config_write_dummy);
1859         install_default(SUPPORT_NODE);
1860         install_element(SUPPORT_NODE, &ournode_exit_cmd);
1861         install_element(SUPPORT_NODE, &ournode_end_cmd);
1862         install_element(SUPPORT_NODE, &cfg_ms_sup_sms_cmd);
1863         install_element(SUPPORT_NODE, &cfg_ms_sup_no_sms_cmd);
1864         install_element(SUPPORT_NODE, &cfg_ms_sup_a5_1_cmd);
1865         install_element(SUPPORT_NODE, &cfg_ms_sup_no_a5_1_cmd);
1866         install_element(SUPPORT_NODE, &cfg_ms_sup_a5_2_cmd);
1867         install_element(SUPPORT_NODE, &cfg_ms_sup_no_a5_2_cmd);
1868         install_element(SUPPORT_NODE, &cfg_ms_sup_a5_3_cmd);
1869         install_element(SUPPORT_NODE, &cfg_ms_sup_no_a5_3_cmd);
1870         install_element(SUPPORT_NODE, &cfg_ms_sup_a5_4_cmd);
1871         install_element(SUPPORT_NODE, &cfg_ms_sup_no_a5_4_cmd);
1872         install_element(SUPPORT_NODE, &cfg_ms_sup_a5_5_cmd);
1873         install_element(SUPPORT_NODE, &cfg_ms_sup_no_a5_5_cmd);
1874         install_element(SUPPORT_NODE, &cfg_ms_sup_a5_6_cmd);
1875         install_element(SUPPORT_NODE, &cfg_ms_sup_no_a5_6_cmd);
1876         install_element(SUPPORT_NODE, &cfg_ms_sup_a5_7_cmd);
1877         install_element(SUPPORT_NODE, &cfg_ms_sup_no_a5_7_cmd);
1878         install_element(SUPPORT_NODE, &cfg_ms_sup_p_gsm_cmd);
1879         install_element(SUPPORT_NODE, &cfg_ms_sup_no_p_gsm_cmd);
1880         install_element(SUPPORT_NODE, &cfg_ms_sup_e_gsm_cmd);
1881         install_element(SUPPORT_NODE, &cfg_ms_sup_no_e_gsm_cmd);
1882         install_element(SUPPORT_NODE, &cfg_ms_sup_r_gsm_cmd);
1883         install_element(SUPPORT_NODE, &cfg_ms_sup_no_r_gsm_cmd);
1884         install_element(SUPPORT_NODE, &cfg_ms_sup_dcs_cmd);
1885         install_element(SUPPORT_NODE, &cfg_ms_sup_no_dcs_cmd);
1886         install_element(SUPPORT_NODE, &cfg_ms_sup_class_900_cmd);
1887         install_element(SUPPORT_NODE, &cfg_ms_sup_class_dcs_cmd);
1888         install_element(SUPPORT_NODE, &cfg_ms_sup_ch_cap_cmd);
1889         install_element(SUPPORT_NODE, &cfg_ms_sup_full_v1_cmd);
1890         install_element(SUPPORT_NODE, &cfg_ms_sup_no_full_v1_cmd);
1891         install_element(SUPPORT_NODE, &cfg_ms_sup_full_v2_cmd);
1892         install_element(SUPPORT_NODE, &cfg_ms_sup_no_full_v2_cmd);
1893         install_element(SUPPORT_NODE, &cfg_ms_sup_full_v3_cmd);
1894         install_element(SUPPORT_NODE, &cfg_ms_sup_no_full_v3_cmd);
1895         install_element(SUPPORT_NODE, &cfg_ms_sup_half_v1_cmd);
1896         install_element(SUPPORT_NODE, &cfg_ms_sup_no_half_v1_cmd);
1897         install_element(SUPPORT_NODE, &cfg_ms_sup_half_v3_cmd);
1898         install_element(SUPPORT_NODE, &cfg_ms_sup_no_half_v3_cmd);
1899         install_element(SUPPORT_NODE, &cfg_ms_sup_min_rxlev_cmd);
1900         install_element(SUPPORT_NODE, &cfg_ms_sup_dsc_max_cmd);
1901         install_node(&testsim_node, config_write_dummy);
1902         install_default(TESTSIM_NODE);
1903         install_element(TESTSIM_NODE, &ournode_exit_cmd);
1904         install_element(TESTSIM_NODE, &ournode_end_cmd);
1905         install_element(TESTSIM_NODE, &cfg_test_imsi_cmd);
1906         install_element(TESTSIM_NODE, &cfg_test_ki_xor_cmd);
1907         install_element(TESTSIM_NODE, &cfg_test_ki_comp128_cmd);
1908         install_element(TESTSIM_NODE, &cfg_test_barr_cmd);
1909         install_element(TESTSIM_NODE, &cfg_test_no_barr_cmd);
1910         install_element(TESTSIM_NODE, &cfg_test_no_rplmn_cmd);
1911         install_element(TESTSIM_NODE, &cfg_test_rplmn_cmd);
1912         install_element(TESTSIM_NODE, &cfg_test_hplmn_cmd);
1913
1914         return 0;
1915 }
1916
1917 void vty_notify(struct osmocom_ms *ms, const char *fmt, ...)
1918 {
1919         struct telnet_connection *connection;
1920         char buffer[1000];
1921         va_list args;
1922         struct vty *vty;
1923
1924         if (fmt) {
1925                 va_start(args, fmt);
1926                 vsnprintf(buffer, sizeof(buffer) - 1, fmt, args);
1927                 buffer[sizeof(buffer) - 1] = '\0';
1928                 va_end(args);
1929
1930                 if (!buffer[0])
1931                         return;
1932         }
1933
1934         llist_for_each_entry(connection, &active_connections, entry) {
1935                 vty = connection->vty;
1936                 if (!vty)
1937                         continue;
1938                 if (!fmt) {
1939                         vty_out(vty, "%s%% (MS %s)%s", VTY_NEWLINE, ms->name,
1940                                 VTY_NEWLINE);
1941                         continue;
1942                 }
1943                 if (buffer[strlen(buffer) - 1] == '\n') {
1944                         buffer[strlen(buffer) - 1] = '\0';
1945                         vty_out(vty, "%% %s%s", buffer, VTY_NEWLINE);
1946                         buffer[strlen(buffer)] = '\n';
1947                 } else
1948                         vty_out(vty, "%% %s", buffer);
1949         }
1950 }
1951