2 * (C) 2010 by Andreas Eversberg <jolly@eversberg.eu>
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.
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.
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.
26 #include <sys/types.h>
28 #include <osmocore/utils.h>
29 #include <osmocore/gsm48.h>
30 #include <osmocore/talloc.h>
32 #include <osmocom/bb/common/osmocom_data.h>
33 #include <osmocom/bb/common/networks.h>
34 #include <osmocom/bb/common/gps.h>
35 #include <osmocom/bb/mobile/mncc.h>
36 #include <osmocom/bb/mobile/transaction.h>
37 #include <osmocom/bb/mobile/vty.h>
38 #include <osmocom/vty/telnet_interface.h>
42 int mncc_call(struct osmocom_ms *ms, char *number);
43 int mncc_hangup(struct osmocom_ms *ms);
44 int mncc_answer(struct osmocom_ms *ms);
45 int mncc_hold(struct osmocom_ms *ms);
46 int mncc_retrieve(struct osmocom_ms *ms, int number);
47 int mncc_dtmf(struct osmocom_ms *ms, char *dtmf);
49 extern struct llist_head ms_list;
50 extern struct llist_head active_connections;
52 struct cmd_node ms_node = {
58 struct cmd_node testsim_node = {
64 struct cmd_node support_node = {
70 static void print_vty(void *priv, const char *fmt, ...)
73 struct vty *vty = priv;
77 vsnprintf(buffer, sizeof(buffer) - 1, fmt, args);
78 buffer[sizeof(buffer) - 1] = '\0';
82 if (buffer[strlen(buffer) - 1] == '\n') {
83 buffer[strlen(buffer) - 1] = '\0';
84 vty_out(vty, "%s%s", buffer, VTY_NEWLINE);
86 vty_out(vty, "%s", buffer);
90 int vty_check_number(struct vty *vty, const char *number)
94 for (i = 0; i < strlen(number); i++) {
95 /* allow international notation with + */
96 if (i == 0 && number[i] == '+')
98 if (!(number[i] >= '0' && number[i] <= '9')
101 && !(number[i] >= 'a' && number[i] <= 'c')) {
102 vty_out(vty, "Invalid digit '%c' of number!%s",
103 number[i], VTY_NEWLINE);
107 if (number[0] == '\0' || (number[0] == '+' && number[1] == '\0')) {
108 vty_out(vty, "Given number has no digits!%s", VTY_NEWLINE);
117 static void vty_restart(struct vty *vty)
121 vty_out(vty, "You must restart for change to take effect!%s",
125 static struct osmocom_ms *get_ms(const char *name, struct vty *vty)
127 struct osmocom_ms *ms;
129 llist_for_each_entry(ms, &ms_list, entity) {
130 if (!strcmp(ms->name, name))
133 vty_out(vty, "MS name '%s' does not exits.%s", name, VTY_NEWLINE);
138 DEFUN(show_ms, show_ms_cmd, "show ms",
139 SHOW_STR "Display available MS entities\n")
141 struct osmocom_ms *ms;
143 llist_for_each_entry(ms, &ms_list, entity) {
144 struct gsm_settings *set = &ms->settings;
146 vty_out(vty, "MS NAME: %s%s", ms->name, VTY_NEWLINE);
147 vty_out(vty, " IMEI: %s%s", set->imei, VTY_NEWLINE);
148 vty_out(vty, " IMEISV: %s%s", set->imeisv, VTY_NEWLINE);
149 if (set->imei_random)
150 vty_out(vty, " IMEI generation: random (%d trailing "
151 "digits)%s", set->imei_random, VTY_NEWLINE);
153 vty_out(vty, " IMEI generation: fixed%s", VTY_NEWLINE);
154 vty_out(vty, " network selection mode: %s%s",
155 (set->plmn_mode == PLMN_MODE_AUTO)
156 ? "automatic" : "manual", VTY_NEWLINE);
162 DEFUN(show_support, show_support_cmd, "show support [ms_name]",
163 SHOW_STR "Display information about MS support\n"
164 "Name of MS (see \"show ms\")")
166 struct osmocom_ms *ms;
169 ms = get_ms(argv[0], vty);
172 gsm_support_dump(ms, print_vty, vty);
174 llist_for_each_entry(ms, &ms_list, entity) {
175 gsm_support_dump(ms, print_vty, vty);
176 vty_out(vty, "%s", VTY_NEWLINE);
183 static void gsm_states_dump(struct osmocom_ms *ms, struct vty *vty)
185 struct gsm_settings *set = &ms->settings;
186 struct gsm_trans *trans;
188 vty_out(vty, "Current state of MS '%s'%s", ms->name, VTY_NEWLINE);
189 if (set->plmn_mode == PLMN_MODE_AUTO)
190 vty_out(vty, " automatic network selection: %s%s",
191 plmn_a_state_names[ms->plmn.state], VTY_NEWLINE);
193 vty_out(vty, " manual network selection: %s%s",
194 plmn_m_state_names[ms->plmn.state], VTY_NEWLINE);
195 vty_out(vty, " cell selection: %s",
196 cs_state_names[ms->cellsel.state]);
197 if (ms->rrlayer.state == GSM48_RR_ST_IDLE && ms->cellsel.selected)
198 vty_out(vty, " (ARFCN %d)", ms->cellsel.sel_arfcn);
199 vty_out(vty, "%s", VTY_NEWLINE);
200 vty_out(vty, " radio ressource layer: %s%s",
201 gsm48_rr_state_names[ms->rrlayer.state], VTY_NEWLINE);
202 vty_out(vty, " mobility management layer: %s",
203 gsm48_mm_state_names[ms->mmlayer.state]);
204 if (ms->mmlayer.state == GSM48_MM_ST_MM_IDLE)
206 gsm48_mm_substate_names[ms->mmlayer.substate]);
207 vty_out(vty, "%s", VTY_NEWLINE);
208 llist_for_each_entry(trans, &ms->trans_list, entry) {
209 vty_out(vty, " call control: %s%s",
210 gsm48_cc_state_name(trans->cc.state), VTY_NEWLINE);
214 DEFUN(show_states, show_states_cmd, "show states [ms_name]",
215 SHOW_STR "Display current states of given MS\n"
216 "Name of MS (see \"show ms\")")
218 struct osmocom_ms *ms;
221 ms = get_ms(argv[0], vty);
224 gsm_states_dump(ms, vty);
226 llist_for_each_entry(ms, &ms_list, entity) {
227 gsm_states_dump(ms, vty);
228 vty_out(vty, "%s", VTY_NEWLINE);
235 DEFUN(show_subscr, show_subscr_cmd, "show subscriber [ms_name]",
236 SHOW_STR "Display information about subscriber\n"
237 "Name of MS (see \"show ms\")")
239 struct osmocom_ms *ms;
242 ms = get_ms(argv[0], vty);
245 gsm_subscr_dump(&ms->subscr, print_vty, vty);
247 llist_for_each_entry(ms, &ms_list, entity) {
248 gsm_subscr_dump(&ms->subscr, print_vty, vty);
249 vty_out(vty, "%s", VTY_NEWLINE);
256 DEFUN(show_cell, show_cell_cmd, "show cell MS_NAME",
257 SHOW_STR "Display information about received cells\n"
258 "Name of MS (see \"show ms\")")
260 struct osmocom_ms *ms;
262 ms = get_ms(argv[0], vty);
266 gsm322_dump_cs_list(&ms->cellsel, GSM322_CS_FLAG_SYSINFO, print_vty,
272 DEFUN(show_cell_si, show_cell_si_cmd, "show cell MS_NAME <0-1023>",
273 SHOW_STR "Display information about received cell\n"
274 "Name of MS (see \"show ms\")\nRadio frequency number")
276 struct osmocom_ms *ms;
278 struct gsm48_sysinfo *s;
280 ms = get_ms(argv[0], vty);
285 if (i < 0 || i > 1023) {
286 vty_out(vty, "Given ARFCN '%s' not in range (0..1023)%s",
287 argv[1], VTY_NEWLINE);
290 s = ms->cellsel.list[i].sysinfo;
292 vty_out(vty, "Given ARFCN '%s' has no sysinfo available%s",
293 argv[1], VTY_NEWLINE);
297 gsm48_sysinfo_dump(s, i, print_vty, vty);
302 DEFUN(show_ba, show_ba_cmd, "show ba MS_NAME [mcc] [mnc]",
303 SHOW_STR "Display information about band allocations\n"
304 "Name of MS (see \"show ms\")\nMobile Country Code\n"
305 "Mobile Network Code")
307 struct osmocom_ms *ms;
308 uint16_t mcc = 0, mnc = 0;
310 ms = get_ms(argv[0], vty);
315 mcc = gsm_input_mcc((char *)argv[1]);
316 mnc = gsm_input_mnc((char *)argv[2]);
318 vty_out(vty, "Given MCC invalid%s", VTY_NEWLINE);
322 vty_out(vty, "Given MNC invalid%s", VTY_NEWLINE);
327 gsm322_dump_ba_list(&ms->cellsel, mcc, mnc, print_vty, vty);
332 DEFUN(show_forb_plmn, show_forb_plmn_cmd, "show forbidden plmn MS_NAME",
333 SHOW_STR "Display information about forbidden cells / networks\n"
334 "Display forbidden PLMNs\nName of MS (see \"show ms\")")
336 struct osmocom_ms *ms;
338 ms = get_ms(argv[0], vty);
342 gsm_subscr_dump_forbidden_plmn(ms, print_vty, vty);
347 DEFUN(show_forb_la, show_forb_la_cmd, "show forbidden location-area MS_NAME",
348 SHOW_STR "Display information about forbidden cells / networks\n"
349 "Display forbidden location areas\nName of MS (see \"show ms\")")
351 struct osmocom_ms *ms;
353 ms = get_ms(argv[0], vty);
357 gsm322_dump_forbidden_la(ms, print_vty, vty);
362 DEFUN(monitor_network, monitor_network_cmd, "monitor network MS_NAME",
363 "Monitor...\nMonitor network information\nName of MS (see \"show ms\")")
365 struct osmocom_ms *ms;
367 ms = get_ms(argv[0], vty);
371 gsm48_rr_start_monitor(ms);
376 DEFUN(no_monitor_network, no_monitor_network_cmd, "no monitor network MS_NAME",
377 NO_STR "Monitor...\nDeactivate monitor of network information\n"
378 "Name of MS (see \"show ms\")")
380 struct osmocom_ms *ms;
382 ms = get_ms(argv[0], vty);
386 gsm48_rr_stop_monitor(ms);
391 DEFUN(sim_test, sim_test_cmd, "sim testcard MS_NAME [mcc] [mnc]",
392 "SIM actions\nInsert test card\nName of MS (see \"show ms\")\n"
393 "Mobile Country Code of RPLMN\nMobile Network Code of RPLMN")
395 struct osmocom_ms *ms;
396 uint16_t mcc = 0x001, mnc = 0x01f;
398 ms = get_ms(argv[0], vty);
402 if (ms->subscr.sim_valid) {
403 vty_out(vty, "SIM already presend, remove first!%s",
409 mcc = gsm_input_mcc((char *)argv[1]);
410 mnc = gsm_input_mnc((char *)argv[2]);
412 vty_out(vty, "Given MCC invalid%s", VTY_NEWLINE);
416 vty_out(vty, "Given MNC invalid%s", VTY_NEWLINE);
421 gsm_subscr_testcard(ms, mcc, mnc);
426 DEFUN(sim_reader, sim_reader_cmd, "sim reader MS_NAME",
427 "SIM actions\nSelect SIM from reader\nName of MS (see \"show ms\")")
429 struct osmocom_ms *ms;
431 ms = get_ms(argv[0], vty);
435 if (ms->subscr.sim_valid) {
436 vty_out(vty, "SIM already presend, remove first!%s",
441 gsm_subscr_simcard(ms);
446 DEFUN(sim_remove, sim_remove_cmd, "sim remove MS_NAME",
447 "SIM actions\nRemove SIM card\nName of MS (see \"show ms\")")
449 struct osmocom_ms *ms;
451 ms = get_ms(argv[0], vty);
455 if (!ms->subscr.sim_valid) {
456 vty_out(vty, "No Sim inserted!%s", VTY_NEWLINE);
460 gsm_subscr_remove(ms);
465 DEFUN(sim_pin, sim_pin_cmd, "sim pin MS_NAME PIN",
466 "SIM actions\nEnter PIN for SIM card\nName of MS (see \"show ms\")\n"
469 struct osmocom_ms *ms;
471 ms = get_ms(argv[0], vty);
475 if (strlen(argv[1]) < 4 || strlen(argv[1]) > 8) {
476 vty_out(vty, "PIN must be in range 4..8!%s", VTY_NEWLINE);
480 if (!ms->subscr.sim_pin_required) {
481 vty_out(vty, "No PIN is required at this time!%s", VTY_NEWLINE);
485 gsm_subscr_sim_pin(ms, (char *)argv[1], "", 0);
490 DEFUN(sim_disable_pin, sim_disable_pin_cmd, "sim disable-pin MS_NAME PIN",
491 "SIM actions\nDisable PIN of SIM card\nName of MS (see \"show ms\")\n"
494 struct osmocom_ms *ms;
496 ms = get_ms(argv[0], vty);
500 if (strlen(argv[1]) < 4 || strlen(argv[1]) > 8) {
501 vty_out(vty, "PIN must be in range 4..8!%s", VTY_NEWLINE);
505 gsm_subscr_sim_pin(ms, (char *)argv[1], "", -1);
510 DEFUN(sim_enable_pin, sim_enable_pin_cmd, "sim enable-pin MS_NAME PIN",
511 "SIM actions\nEnable PIN of SIM card\nName of MS (see \"show ms\")\n"
514 struct osmocom_ms *ms;
516 ms = get_ms(argv[0], vty);
520 if (strlen(argv[1]) < 4 || strlen(argv[1]) > 8) {
521 vty_out(vty, "PIN must be in range 4..8!%s", VTY_NEWLINE);
525 gsm_subscr_sim_pin(ms, (char *)argv[1], "", 1);
530 DEFUN(sim_change_pin, sim_change_pin_cmd, "sim change-pin MS_NAME OLD NEW",
531 "SIM actions\nChange PIN of SIM card\nName of MS (see \"show ms\")\n"
532 "Old PIN number\nNew PIN number")
534 struct osmocom_ms *ms;
536 ms = get_ms(argv[0], vty);
540 if (strlen(argv[1]) < 4 || strlen(argv[1]) > 8) {
541 vty_out(vty, "Old PIN must be in range 4..8!%s", VTY_NEWLINE);
544 if (strlen(argv[2]) < 4 || strlen(argv[2]) > 8) {
545 vty_out(vty, "New PIN must be in range 4..8!%s", VTY_NEWLINE);
549 gsm_subscr_sim_pin(ms, (char *)argv[1], (char *)argv[2], 2);
554 DEFUN(sim_unblock_pin, sim_unblock_pin_cmd, "sim unblock-pin MS_NAME PUC NEW",
555 "SIM actions\nChange PIN of SIM card\nName of MS (see \"show ms\")\n"
556 "Personal Unblock Key\nNew PIN number")
558 struct osmocom_ms *ms;
560 ms = get_ms(argv[0], vty);
564 if (strlen(argv[1]) != 8) {
565 vty_out(vty, "PUC must be 8 digits!%s", VTY_NEWLINE);
568 if (strlen(argv[2]) < 4 || strlen(argv[2]) > 8) {
569 vty_out(vty, "PIN must be in range 4..8!%s", VTY_NEWLINE);
573 gsm_subscr_sim_pin(ms, (char *)argv[1], (char *)argv[2], 99);
578 DEFUN(sim_lai, sim_lai_cmd, "sim lai MS_NAME MCC MNC LAC",
579 "SIM actions\nChange LAI of SIM card\nName of MS (see \"show ms\")\n"
580 "Mobile Country Code\nMobile Network Code\nLocation Area Code "
581 " (use 0000 to remove LAI)")
583 struct osmocom_ms *ms;
584 uint16_t mcc = gsm_input_mcc((char *)argv[1]),
585 mnc = gsm_input_mnc((char *)argv[2]),
586 lac = strtoul(argv[3], NULL, 16);
588 ms = get_ms(argv[0], vty);
593 vty_out(vty, "Given MCC invalid%s", VTY_NEWLINE);
597 vty_out(vty, "Given MNC invalid%s", VTY_NEWLINE);
601 ms->subscr.mcc = mcc;
602 ms->subscr.mnc = mnc;
603 ms->subscr.lac = lac;
604 ms->subscr.tmsi = 0xffffffff;
606 gsm_subscr_write_loci(ms);
611 DEFUN(network_select, network_select_cmd, "network select MS_NAME MCC MNC",
612 "Select ...\nSelect Network\nName of MS (see \"show ms\")\n"
613 "Mobile Country Code\nMobile Network Code")
615 struct osmocom_ms *ms;
616 struct gsm322_plmn *plmn;
618 struct gsm322_msg *ngm;
619 struct gsm322_plmn_list *temp;
620 uint16_t mcc = gsm_input_mcc((char *)argv[1]),
621 mnc = gsm_input_mnc((char *)argv[2]);
624 ms = get_ms(argv[0], vty);
630 vty_out(vty, "Given MCC invalid%s", VTY_NEWLINE);
634 vty_out(vty, "Given MNC invalid%s", VTY_NEWLINE);
638 llist_for_each_entry(temp, &plmn->sorted_plmn, entry)
639 if (temp->mcc == mcc && temp->mnc == mnc)
642 vty_out(vty, "Network not in list!%s", VTY_NEWLINE);
646 nmsg = gsm322_msgb_alloc(GSM322_EVENT_CHOOSE_PLMN);
649 ngm = (struct gsm322_msg *) nmsg->data;
652 gsm322_plmn_sendmsg(ms, nmsg);
657 DEFUN(call, call_cmd, "call MS_NAME (NUMBER|emergency|answer|hangup|hold)",
658 "Make a call\nName of MS (see \"show ms\")\nPhone number to call "
659 "(Use digits '0123456789*#abc', and '+' to dial international)\n"
660 "Make an emergency call\nAnswer an incomming call\nHangup a call\n"
661 "Hold current active call\n")
663 struct osmocom_ms *ms;
664 struct gsm_settings *set;
665 struct gsm_settings_abbrev *abbrev;
668 ms = get_ms(argv[0], vty);
673 if (set->ch_cap == GSM_CAP_SDCCH) {
674 vty_out(vty, "Basic call is not supported for SDCCH only "
675 "mobile%s", VTY_NEWLINE);
679 number = (char *)argv[1];
680 if (!strcmp(number, "emergency"))
681 mncc_call(ms, number);
682 else if (!strcmp(number, "answer"))
684 else if (!strcmp(number, "hangup"))
686 else if (!strcmp(number, "hold"))
689 llist_for_each_entry(abbrev, &set->abbrev, list) {
690 if (!strcmp(number, abbrev->abbrev)) {
691 number = abbrev->number;
692 vty_out(vty, "Dialing number '%s'%s", number,
697 if (vty_check_number(vty, number))
699 mncc_call(ms, number);
705 DEFUN(call_retr, call_retr_cmd, "call MS_NAME retrieve [number]",
706 "Make a call\nName of MS (see \"show ms\")\n"
707 "Retrieve call on hold\nNumber of call to retrieve")
709 struct osmocom_ms *ms;
711 ms = get_ms(argv[0], vty);
715 mncc_retrieve(ms, (argc > 1) ? atoi(argv[1]) : 0);
720 DEFUN(call_dtmf, call_dtmf_cmd, "call MS_NAME dtmf DIGITS",
721 "Make a call\nName of MS (see \"show ms\")\n"
722 "One or more DTMF digits to transmit")
724 struct osmocom_ms *ms;
725 struct gsm_settings *set;
727 ms = get_ms(argv[0], vty);
733 vty_out(vty, "DTMF not supported, please enable!%s",
738 mncc_dtmf(ms, (char *)argv[1]);
743 DEFUN(network_show, network_show_cmd, "network show MS_NAME",
744 "Network ...\nShow results of network search (again)\n"
745 "Name of MS (see \"show ms\")")
747 struct osmocom_ms *ms;
748 struct gsm_settings *set;
749 struct gsm322_plmn *plmn;
750 struct gsm322_plmn_list *temp;
752 ms = get_ms(argv[0], vty);
758 if (set->plmn_mode != PLMN_MODE_AUTO
759 && plmn->state != GSM322_M3_NOT_ON_PLMN) {
760 vty_out(vty, "Start network search first!%s", VTY_NEWLINE);
764 llist_for_each_entry(temp, &plmn->sorted_plmn, entry)
765 vty_out(vty, " Network %s, %s (%s, %s)%s",
766 gsm_print_mcc(temp->mcc), gsm_print_mnc(temp->mnc),
767 gsm_get_mcc(temp->mcc),
768 gsm_get_mnc(temp->mcc, temp->mnc), VTY_NEWLINE);
773 DEFUN(network_search, network_search_cmd, "network search MS_NAME",
774 "Network ...\nTrigger network search\nName of MS (see \"show ms\")")
776 struct osmocom_ms *ms;
779 ms = get_ms(argv[0], vty);
783 nmsg = gsm322_msgb_alloc(GSM322_EVENT_USER_RESEL);
786 gsm322_plmn_sendmsg(ms, nmsg);
791 DEFUN(cfg_gps_enable, cfg_gps_enable_cmd, "gps enable",
796 vty_out(vty, "Failed to open GPS device!%s", VTY_NEWLINE);
804 DEFUN(cfg_no_gps_enable, cfg_no_gps_enable_cmd, "no gps enable",
805 NO_STR "Disable GPS receiver")
814 DEFUN(cfg_gps_device, cfg_gps_device_cmd, "gps device DEVICE",
815 "GPS receiver\nSelect serial device\n"
816 "Full path of serial device including /dev/")
818 strncpy(gps.device, argv[0], sizeof(gps.device));
819 gps.device[sizeof(gps.device) - 1] = '\0';
823 vty_out(vty, "Failed to open GPS device!%s",
832 DEFUN(cfg_gps_baud, cfg_gps_baud_cmd, "gps baudrate "
833 "(default|4800|""9600|19200|38400|57600|115200)",
834 "GPS receiver\nSelect baud rate\nDefault, don't modify\n\n\n\n\n\n")
836 if (argv[0][0] == 'd')
839 gps.baud = atoi(argv[0]);
844 vty_out(vty, "Failed to open GPS device!%s",
854 DEFUN(cfg_ms, cfg_ms_cmd, "ms MS_NAME",
855 "Select a mobile station to configure\nName of MS (see \"show ms\")")
857 struct osmocom_ms *ms;
859 ms = get_ms(argv[0], vty);
869 #define SUP_WRITE(item, cmd) \
871 vty_out(vty, " %s%s%s", (set->item) ? "" : "no ", cmd, \
874 static void config_write_ms_single(struct vty *vty, struct osmocom_ms *ms)
876 struct gsm_settings *set = &ms->settings;
877 struct gsm_support *sup = &ms->support;
878 struct gsm_settings_abbrev *abbrev;
880 vty_out(vty, "ms %s%s", ms->name, VTY_NEWLINE);
881 switch(set->sim_type) {
882 case GSM_SIM_TYPE_NONE:
883 vty_out(vty, " sim none%s", VTY_NEWLINE);
885 case GSM_SIM_TYPE_READER:
886 vty_out(vty, " sim reader%s", VTY_NEWLINE);
888 case GSM_SIM_TYPE_TEST:
889 vty_out(vty, " sim test%s", VTY_NEWLINE);
892 vty_out(vty, " network-selection-mode %s%s", (set->plmn_mode
893 == PLMN_MODE_AUTO) ? "auto" : "manual", VTY_NEWLINE);
894 vty_out(vty, " imei %s %s%s", set->imei,
895 set->imeisv + strlen(set->imei), VTY_NEWLINE);
896 if (set->imei_random)
897 vty_out(vty, " imei-random %d%s", set->imei_random,
900 vty_out(vty, " imei-fixed%s", VTY_NEWLINE);
901 if (set->emergency_imsi[0])
902 vty_out(vty, " emergency-imsi %s%s", set->emergency_imsi,
905 vty_out(vty, " no emergency-imsi%s", VTY_NEWLINE);
906 vty_out(vty, " %scall-waiting%s", (set->cw) ? "" : "no ", VTY_NEWLINE);
907 vty_out(vty, " %sauto-answer%s", (set->auto_answer) ? "" : "no ",
909 vty_out(vty, " %sclip%s", (set->clip) ? "" : "no ", VTY_NEWLINE);
910 vty_out(vty, " %sclir%s", (set->clir) ? "" : "no ", VTY_NEWLINE);
911 if (set->alter_tx_power)
912 if (set->alter_tx_power_value)
913 vty_out(vty, " tx-power %d%s",
914 set->alter_tx_power_value, VTY_NEWLINE);
916 vty_out(vty, " tx-power full%s", VTY_NEWLINE);
918 vty_out(vty, " tx-power auto%s", VTY_NEWLINE);
919 if (set->alter_delay)
920 vty_out(vty, " simulated-delay %d%s", set->alter_delay,
923 vty_out(vty, " no simulated-delay%s", VTY_NEWLINE);
925 vty_out(vty, " stick %d%s", set->stick_arfcn,
928 vty_out(vty, " no stick%s", VTY_NEWLINE);
930 vty_out(vty, " no location-updating%s", VTY_NEWLINE);
932 vty_out(vty, " location-updating%s", VTY_NEWLINE);
933 if (set->full_v1 || set->full_v2 || set->full_v3) {
934 /* mandatory anyway */
935 vty_out(vty, " codec full-speed%s%s",
936 (!set->half_prefer) ? " prefer" : "",
939 if (set->half_v1 || set->half_v3) {
941 vty_out(vty, " codec half-speed%s%s",
942 (set->half_prefer) ? " prefer" : "",
945 vty_out(vty, " no codec half-speed%s", VTY_NEWLINE);
947 if (llist_empty(&set->abbrev))
948 vty_out(vty, " no abbrev%s", VTY_NEWLINE);
950 llist_for_each_entry(abbrev, &set->abbrev, list)
951 vty_out(vty, " abbrev %s %s%s%s%s", abbrev->abbrev,
952 abbrev->number, (abbrev->name[0]) ? " " : "",
953 abbrev->name, VTY_NEWLINE);
955 vty_out(vty, " support%s", VTY_NEWLINE);
956 SUP_WRITE(sms_ptp, "sms");
957 SUP_WRITE(a5_1, "a5/1");
958 SUP_WRITE(a5_2, "a5/2");
959 SUP_WRITE(a5_3, "a5/3");
960 SUP_WRITE(a5_4, "a5/4");
961 SUP_WRITE(a5_5, "a5/5");
962 SUP_WRITE(a5_6, "a5/6");
963 SUP_WRITE(a5_7, "a5/7");
964 SUP_WRITE(p_gsm, "p-gsm");
965 SUP_WRITE(e_gsm, "e-gsm");
966 SUP_WRITE(r_gsm, "r-gsm");
967 SUP_WRITE(dcs, "dcs");
968 vty_out(vty, " class-900 %d%s", set->class_900, VTY_NEWLINE);
969 vty_out(vty, " class-dcs %d%s", set->class_dcs, VTY_NEWLINE);
970 switch (set->ch_cap) {
972 vty_out(vty, " channel-capability sdcch%s", VTY_NEWLINE);
974 case GSM_CAP_SDCCH_TCHF:
975 vty_out(vty, " channel-capability sdcch+tchf%s", VTY_NEWLINE);
977 case GSM_CAP_SDCCH_TCHF_TCHH:
978 vty_out(vty, " channel-capability sdcch+tchf+tchh%s",
982 SUP_WRITE(full_v1, "full-speech-v1");
983 SUP_WRITE(full_v2, "full-speech-v2");
984 SUP_WRITE(full_v3, "full-speech-v3");
985 SUP_WRITE(half_v1, "half-speech-v1");
986 SUP_WRITE(half_v3, "half-speech-v3");
987 vty_out(vty, " min-rxlev %d%s", set->min_rxlev_db, VTY_NEWLINE);
988 vty_out(vty, " dsc-max %d%s", set->dsc_max, VTY_NEWLINE);
989 vty_out(vty, " exit%s", VTY_NEWLINE);
990 vty_out(vty, " test-sim%s", VTY_NEWLINE);
991 vty_out(vty, " imsi %s%s", set->test_imsi, VTY_NEWLINE);
992 switch (set->test_ki_type) {
993 case GSM_SIM_KEY_XOR:
994 vty_out(vty, " ki xor %s%s", hexdump(set->test_ki, 12),
997 case GSM_SIM_KEY_COMP128:
998 vty_out(vty, " ki comp128 %s%s", hexdump(set->test_ki, 16),
1002 vty_out(vty, " %sbarred-access%s", (set->test_barr) ? "" : "no ",
1004 if (set->test_rplmn_valid)
1005 vty_out(vty, " rplmn %s %s%s",
1006 gsm_print_mcc(set->test_rplmn_mcc),
1007 gsm_print_mnc(set->test_rplmn_mnc),
1010 vty_out(vty, " no rplmn%s", VTY_NEWLINE);
1011 vty_out(vty, " hplmn-search %s%s", (set->test_always) ? "everywhere"
1012 : "foreign-country", VTY_NEWLINE);
1013 vty_out(vty, " exit%s", VTY_NEWLINE);
1014 vty_out(vty, "exit%s", VTY_NEWLINE);
1015 vty_out(vty, "!%s", VTY_NEWLINE);
1018 static int config_write_ms(struct vty *vty)
1020 struct osmocom_ms *ms;
1022 vty_out(vty, "gps device %s%s", gps.device, VTY_NEWLINE);
1024 vty_out(vty, "gps baudrate %d%s", gps.baud, VTY_NEWLINE);
1026 vty_out(vty, "gps baudrate default%s", VTY_NEWLINE);
1027 vty_out(vty, "%sgps enable%s", (gps.enable) ? "" : "no ", VTY_NEWLINE);
1028 vty_out(vty, "!%s", VTY_NEWLINE);
1030 llist_for_each_entry(ms, &ms_list, entity)
1031 config_write_ms_single(vty, ms);
1036 DEFUN(cfg_ms_sim, cfg_ms_sim_cmd, "sim (none|reader|test)",
1037 "Set SIM card type when powering on\nNo SIM interted\n"
1038 "Use SIM from reader\nTest SIM inserted")
1040 struct osmocom_ms *ms = vty->index;
1041 struct gsm_settings *set = &ms->settings;
1043 switch (argv[0][0]) {
1045 set->sim_type = GSM_SIM_TYPE_NONE;
1048 set->sim_type = GSM_SIM_TYPE_READER;
1051 set->sim_type = GSM_SIM_TYPE_TEST;
1054 vty_out(vty, "unknown SIM type%s", VTY_NEWLINE);
1062 DEFUN(cfg_ms_mode, cfg_ms_mode_cmd, "network-selection-mode (auto|manual)",
1063 "Set network selection mode\nAutomatic network selection\n"
1064 "Manual network selection")
1066 struct osmocom_ms *ms = vty->index;
1067 struct gsm_settings *set = &ms->settings;
1070 if (!ms->plmn.state) {
1071 if (argv[0][0] == 'a')
1072 set->plmn_mode = PLMN_MODE_AUTO;
1074 set->plmn_mode = PLMN_MODE_MANUAL;
1078 if (argv[0][0] == 'a')
1079 nmsg = gsm322_msgb_alloc(GSM322_EVENT_SEL_AUTO);
1081 nmsg = gsm322_msgb_alloc(GSM322_EVENT_SEL_MANUAL);
1084 gsm322_plmn_sendmsg(ms, nmsg);
1089 DEFUN(cfg_ms_imei, cfg_ms_imei_cmd, "imei IMEI [SV]",
1090 "Set IMEI (enter without control digit)\n15 Digits IMEI\n"
1091 "Software version digit")
1093 struct osmocom_ms *ms = vty->index;
1094 struct gsm_settings *set = &ms->settings;
1095 char *error, *sv = "0";
1098 sv = (char *)argv[1];
1100 error = gsm_check_imei(argv[0], sv);
1102 vty_out(vty, "%s%s", error, VTY_NEWLINE);
1106 strcpy(set->imei, argv[0]);
1107 strcpy(set->imeisv, argv[0]);
1108 strcpy(set->imeisv + 15, sv);
1113 DEFUN(cfg_ms_imei_fixed, cfg_ms_imei_fixed_cmd, "imei-fixed",
1114 "Use fixed IMEI on every power on")
1116 struct osmocom_ms *ms = vty->index;
1117 struct gsm_settings *set = &ms->settings;
1119 set->imei_random = 0;
1125 DEFUN(cfg_ms_imei_random, cfg_ms_imei_random_cmd, "imei-random <0-15>",
1126 "Use random IMEI on every power on\n"
1127 "Number of trailing digits to randomize")
1129 struct osmocom_ms *ms = vty->index;
1130 struct gsm_settings *set = &ms->settings;
1132 set->imei_random = atoi(argv[0]);
1138 DEFUN(cfg_ms_emerg_imsi, cfg_ms_emerg_imsi_cmd, "emergency-imsi IMSI",
1139 "Use special IMSI for emergency calls\n15 digits IMSI")
1141 struct osmocom_ms *ms = vty->index;
1142 struct gsm_settings *set = &ms->settings;
1145 error = gsm_check_imsi(argv[0]);
1147 vty_out(vty, "%s%s", error, VTY_NEWLINE);
1150 strcpy(set->emergency_imsi, argv[0]);
1155 DEFUN(cfg_ms_no_emerg_imsi, cfg_ms_no_emerg_imsi_cmd, "no emergency-imsi",
1156 NO_STR "Use IMSI of SIM or IMEI for emergency calls")
1158 struct osmocom_ms *ms = vty->index;
1159 struct gsm_settings *set = &ms->settings;
1161 set->emergency_imsi[0] = '\0';
1166 DEFUN(cfg_no_cw, cfg_ms_no_cw_cmd, "no call-waiting",
1167 NO_STR "Disallow waiting calls")
1169 struct osmocom_ms *ms = vty->index;
1170 struct gsm_settings *set = &ms->settings;
1177 DEFUN(cfg_cw, cfg_ms_cw_cmd, "call-waiting",
1178 "Allow waiting calls")
1180 struct osmocom_ms *ms = vty->index;
1181 struct gsm_settings *set = &ms->settings;
1188 DEFUN(cfg_no_auto_answer, cfg_ms_no_auto_answer_cmd, "no auto-answer",
1189 NO_STR "Disable auto-answering calls")
1191 struct osmocom_ms *ms = vty->index;
1192 struct gsm_settings *set = &ms->settings;
1194 set->auto_answer = 0;
1199 DEFUN(cfg_auto_answer, cfg_ms_auto_answer_cmd, "auto-answer",
1200 "Enable auto-answering calls")
1202 struct osmocom_ms *ms = vty->index;
1203 struct gsm_settings *set = &ms->settings;
1205 set->auto_answer = 1;
1210 DEFUN(cfg_clip, cfg_ms_clip_cmd, "clip",
1211 "Force caller ID presentation")
1213 struct osmocom_ms *ms = vty->index;
1214 struct gsm_settings *set = &ms->settings;
1222 DEFUN(cfg_clir, cfg_ms_clir_cmd, "clir",
1223 "Force caller ID restriction")
1225 struct osmocom_ms *ms = vty->index;
1226 struct gsm_settings *set = &ms->settings;
1234 DEFUN(cfg_no_clip, cfg_ms_no_clip_cmd, "no clip",
1235 NO_STR "Disable forcing of caller ID presentation")
1237 struct osmocom_ms *ms = vty->index;
1238 struct gsm_settings *set = &ms->settings;
1245 DEFUN(cfg_no_clir, cfg_ms_no_clir_cmd, "no clir",
1246 NO_STR "Disable forcing of caller ID restriction")
1248 struct osmocom_ms *ms = vty->index;
1249 struct gsm_settings *set = &ms->settings;
1256 DEFUN(cfg_ms_tx_power, cfg_ms_tx_power_cmd, "tx-power (auto|full)",
1257 "Set the way to choose transmit power\nControlled by BTS\n"
1258 "Always full power\nFixed GSM power value if supported")
1260 struct osmocom_ms *ms = vty->index;
1261 struct gsm_settings *set = &ms->settings;
1263 switch (argv[0][0]) {
1265 set->alter_tx_power = 0;
1268 set->alter_tx_power = 1;
1269 set->alter_tx_power_value = 0;
1276 DEFUN(cfg_ms_tx_power_val, cfg_ms_tx_power_val_cmd, "tx-power <0-31>",
1277 "Set the way to choose transmit power\n"
1278 "Fixed GSM power value if supported")
1280 struct osmocom_ms *ms = vty->index;
1281 struct gsm_settings *set = &ms->settings;
1283 set->alter_tx_power = 1;
1284 set->alter_tx_power_value = atoi(argv[0]);
1289 DEFUN(cfg_ms_sim_delay, cfg_ms_sim_delay_cmd, "simulated-delay <-128-127>",
1290 "Simulate a lower or higher distance from the BTS\n"
1291 "Delay in half bits (distance in 553.85 meter steps)")
1293 struct osmocom_ms *ms = vty->index;
1294 struct gsm_settings *set = &ms->settings;
1296 set->alter_delay = atoi(argv[0]);
1297 gsm48_rr_alter_delay(ms);
1302 DEFUN(cfg_ms_no_sim_delay, cfg_ms_no_sim_delay_cmd, "no simulated-delay",
1303 NO_STR "Do not simulate a lower or higher distance from the BTS")
1305 struct osmocom_ms *ms = vty->index;
1306 struct gsm_settings *set = &ms->settings;
1308 set->alter_delay = 0;
1309 gsm48_rr_alter_delay(ms);
1314 DEFUN(cfg_ms_stick, cfg_ms_stick_cmd, "stick <0-1023>",
1315 "Stick to the given cell\nARFCN of the cell to stick to")
1317 struct osmocom_ms *ms = vty->index;
1318 struct gsm_settings *set = &ms->settings;
1321 set->stick_arfcn = atoi(argv[0]);
1326 DEFUN(cfg_ms_no_stick, cfg_ms_no_stick_cmd, "no stick",
1327 NO_STR "Do not stick to any cell")
1329 struct osmocom_ms *ms = vty->index;
1330 struct gsm_settings *set = &ms->settings;
1337 DEFUN(cfg_ms_lupd, cfg_ms_lupd_cmd, "location-updating",
1338 "Allow location updating")
1340 struct osmocom_ms *ms = vty->index;
1341 struct gsm_settings *set = &ms->settings;
1348 DEFUN(cfg_ms_no_lupd, cfg_ms_no_lupd_cmd, "no location-updating",
1349 NO_STR "Do not allow location updating")
1351 struct osmocom_ms *ms = vty->index;
1352 struct gsm_settings *set = &ms->settings;
1359 DEFUN(cfg_codec_full, cfg_ms_codec_full_cmd, "codec full-speed",
1360 "Enable codec\nFull speed speech codec")
1362 struct osmocom_ms *ms = vty->index;
1363 struct gsm_settings *set = &ms->settings;
1365 if (!set->full_v1 && !set->full_v2 && !set->full_v3) {
1366 vty_out(vty, "Full-rate codec not supported%s", VTY_NEWLINE);
1373 DEFUN(cfg_codec_full_pref, cfg_ms_codec_full_pref_cmd, "codec full-speed "
1375 "Enable codec\nFull speed speech codec\nPrefer this codec")
1377 struct osmocom_ms *ms = vty->index;
1378 struct gsm_settings *set = &ms->settings;
1380 if (!set->full_v1 && !set->full_v2 && !set->full_v3) {
1381 vty_out(vty, "Full-rate codec not supported%s", VTY_NEWLINE);
1385 set->half_prefer = 0;
1390 DEFUN(cfg_codec_half, cfg_ms_codec_half_cmd, "codec half-speed",
1391 "Enable codec\nHalf speed speech codec")
1393 struct osmocom_ms *ms = vty->index;
1394 struct gsm_settings *set = &ms->settings;
1396 if (!set->half_v1 && !set->half_v3) {
1397 vty_out(vty, "Half-rate codec not supported%s", VTY_NEWLINE);
1406 DEFUN(cfg_codec_half_pref, cfg_ms_codec_half_pref_cmd, "codec half-speed "
1408 "Enable codec\nHalf speed speech codec\nPrefer this codec")
1410 struct osmocom_ms *ms = vty->index;
1411 struct gsm_settings *set = &ms->settings;
1413 if (!set->half_v1 && !set->half_v3) {
1414 vty_out(vty, "Half-rate codec not supported%s", VTY_NEWLINE);
1419 set->half_prefer = 1;
1424 DEFUN(cfg_no_codec_half, cfg_ms_no_codec_half_cmd, "no codec half-speed",
1425 NO_STR "Disable codec\nHalf speed speech codec")
1427 struct osmocom_ms *ms = vty->index;
1428 struct gsm_settings *set = &ms->settings;
1430 if (!set->half_v1 && !set->half_v3) {
1431 vty_out(vty, "Half-rate codec not supported%s", VTY_NEWLINE);
1436 set->half_prefer = 0;
1441 DEFUN(cfg_abbrev, cfg_ms_abbrev_cmd, "abbrev ABBREVIATION NUMBER [name]",
1442 "Store given abbreviation number\n1-3 digits abbreviation\n"
1443 "Number to store for the abbreviation "
1444 "(Use digits '0123456789*#abc', and '+' to dial international)\n"
1445 "Name of the abbreviation")
1447 struct osmocom_ms *ms = vty->index;
1448 struct gsm_settings *set = &ms->settings;
1449 struct gsm_settings_abbrev *abbrev;
1452 llist_for_each_entry(abbrev, &set->abbrev, list) {
1453 if (!strcmp(argv[0], abbrev->abbrev)) {
1454 vty_out(vty, "Given abbreviation '%s' already stored, "
1455 "delete first!%s", argv[0], VTY_NEWLINE);
1460 if (strlen(argv[0]) >= sizeof(abbrev->abbrev)) {
1461 vty_out(vty, "Given abbreviation too long%s", VTY_NEWLINE);
1465 for (i = 0; i < strlen(argv[0]); i++) {
1466 if (argv[0][i] < '0' || argv[0][i] > '9') {
1467 vty_out(vty, "Given abbreviation must have digits "
1468 "0..9 only!%s", VTY_NEWLINE);
1473 if (vty_check_number(vty, argv[1]))
1476 abbrev = talloc_zero(l23_ctx, struct gsm_settings_abbrev);
1478 vty_out(vty, "No Memory!%s", VTY_NEWLINE);
1481 llist_add_tail(&abbrev->list, &set->abbrev);
1482 strncpy(abbrev->abbrev, argv[0], sizeof(abbrev->abbrev) - 1);
1483 strncpy(abbrev->number, argv[1], sizeof(abbrev->number) - 1);
1485 strncpy(abbrev->name, argv[2], sizeof(abbrev->name) - 1);
1490 DEFUN(cfg_no_abbrev, cfg_ms_no_abbrev_cmd, "no abbrev [abbreviation]",
1491 NO_STR "Remove given abbreviation number or all numbers\n"
1492 "Abbreviation number to remove")
1494 struct osmocom_ms *ms = vty->index;
1495 struct gsm_settings *set = &ms->settings;
1496 struct gsm_settings_abbrev *abbrev, *abbrev2;
1497 uint8_t deleted = 0;
1499 llist_for_each_entry_safe(abbrev, abbrev2, &set->abbrev, list) {
1500 if (argc < 1 || !strcmp(argv[0], abbrev->abbrev)) {
1501 llist_del(&abbrev->list);
1506 if (argc >= 1 && !deleted) {
1507 vty_out(vty, "Given abbreviation '%s' not found!%s",
1508 argv[0], VTY_NEWLINE);
1515 static int config_write_dummy(struct vty *vty)
1520 /* per support config */
1521 DEFUN(cfg_ms_support, cfg_ms_support_cmd, "support",
1522 "Define supported features")
1524 vty->node = SUPPORT_NODE;
1529 #define SUP_EN(cfg, cfg_cmd, item, cmd, desc, restart) \
1530 DEFUN(cfg, cfg_cmd, cmd, "Enable " desc "support") \
1532 struct osmocom_ms *ms = vty->index; \
1533 struct gsm_settings *set = &ms->settings; \
1534 struct gsm_support *sup = &ms->support; \
1536 vty_out(vty, desc " not supported%s", VTY_NEWLINE); \
1538 return CMD_SUCCESS; \
1539 return CMD_WARNING; \
1544 return CMD_SUCCESS; \
1547 #define SUP_DI(cfg, cfg_cmd, item, cmd, desc, restart) \
1548 DEFUN(cfg, cfg_cmd, "no " cmd, NO_STR "Disable " desc " support") \
1550 struct osmocom_ms *ms = vty->index; \
1551 struct gsm_settings *set = &ms->settings; \
1552 struct gsm_support *sup = &ms->support; \
1554 vty_out(vty, desc " not supported%s", VTY_NEWLINE); \
1556 return CMD_SUCCESS; \
1557 return CMD_WARNING; \
1562 return CMD_SUCCESS; \
1565 #define SET_EN(cfg, cfg_cmd, item, cmd, desc, restart) \
1566 DEFUN(cfg, cfg_cmd, cmd, "Enable " desc "support") \
1568 struct osmocom_ms *ms = vty->index; \
1569 struct gsm_settings *set = &ms->settings; \
1573 return CMD_SUCCESS; \
1576 #define SET_DI(cfg, cfg_cmd, item, cmd, desc, restart) \
1577 DEFUN(cfg, cfg_cmd, "no " cmd, NO_STR "Disable " desc " support") \
1579 struct osmocom_ms *ms = vty->index; \
1580 struct gsm_settings *set = &ms->settings; \
1584 return CMD_SUCCESS; \
1587 SET_EN(cfg_ms_sup_dtmf, cfg_ms_sup_dtmf_cmd, cc_dtmf, "dtmf", "DTMF", 0);
1588 SET_DI(cfg_ms_sup_no_dtmf, cfg_ms_sup_no_dtmf_cmd, cc_dtmf, "dtmf", "DTMF", 0);
1589 SUP_EN(cfg_ms_sup_sms, cfg_ms_sup_sms_cmd, sms_ptp, "sms", "SMS", 0);
1590 SUP_DI(cfg_ms_sup_no_sms, cfg_ms_sup_no_sms_cmd, sms_ptp, "sms", "SMS", 0);
1591 SUP_EN(cfg_ms_sup_a5_1, cfg_ms_sup_a5_1_cmd, a5_1, "a5/1", "A5/1", 0);
1592 SUP_DI(cfg_ms_sup_no_a5_1, cfg_ms_sup_no_a5_1_cmd, a5_1, "a5/1", "A5/1", 0);
1593 SUP_EN(cfg_ms_sup_a5_2, cfg_ms_sup_a5_2_cmd, a5_2, "a5/2", "A5/2", 0);
1594 SUP_DI(cfg_ms_sup_no_a5_2, cfg_ms_sup_no_a5_2_cmd, a5_2, "a5/2", "A5/2", 0);
1595 SUP_EN(cfg_ms_sup_a5_3, cfg_ms_sup_a5_3_cmd, a5_3, "a5/3", "A5/3", 0);
1596 SUP_DI(cfg_ms_sup_no_a5_3, cfg_ms_sup_no_a5_3_cmd, a5_3, "a5/3", "A5/3", 0);
1597 SUP_EN(cfg_ms_sup_a5_4, cfg_ms_sup_a5_4_cmd, a5_4, "a5/4", "A5/4", 0);
1598 SUP_DI(cfg_ms_sup_no_a5_4, cfg_ms_sup_no_a5_4_cmd, a5_4, "a5/4", "A5/4", 0);
1599 SUP_EN(cfg_ms_sup_a5_5, cfg_ms_sup_a5_5_cmd, a5_5, "a5/5", "A5/5", 0);
1600 SUP_DI(cfg_ms_sup_no_a5_5, cfg_ms_sup_no_a5_5_cmd, a5_5, "a5/5", "A5/5", 0);
1601 SUP_EN(cfg_ms_sup_a5_6, cfg_ms_sup_a5_6_cmd, a5_6, "a5/6", "A5/6", 0);
1602 SUP_DI(cfg_ms_sup_no_a5_6, cfg_ms_sup_no_a5_6_cmd, a5_6, "a5/6", "A5/6", 0);
1603 SUP_EN(cfg_ms_sup_a5_7, cfg_ms_sup_a5_7_cmd, a5_7, "a5/7", "A5/7", 0);
1604 SUP_DI(cfg_ms_sup_no_a5_7, cfg_ms_sup_no_a5_7_cmd, a5_7, "a5/7", "A5/7", 1);
1605 SUP_EN(cfg_ms_sup_p_gsm, cfg_ms_sup_p_gsm_cmd, p_gsm, "p-gsm", "P-GSM (900)",
1607 SUP_DI(cfg_ms_sup_no_p_gsm, cfg_ms_sup_no_p_gsm_cmd, p_gsm, "p-gsm",
1609 SUP_EN(cfg_ms_sup_e_gsm, cfg_ms_sup_e_gsm_cmd, e_gsm, "e-gsm", "E-GSM (850)",
1611 SUP_DI(cfg_ms_sup_no_e_gsm, cfg_ms_sup_no_e_gsm_cmd, e_gsm, "e-gsm",
1613 SUP_EN(cfg_ms_sup_r_gsm, cfg_ms_sup_r_gsm_cmd, r_gsm, "r-gsm", "R-GSM (850)",
1615 SUP_DI(cfg_ms_sup_no_r_gsm, cfg_ms_sup_no_r_gsm_cmd, r_gsm, "r-gsm",
1617 SUP_EN(cfg_ms_sup_dcs, cfg_ms_sup_dcs_cmd, dcs, "dcs", "DCS (1800)", 0);
1618 SUP_DI(cfg_ms_sup_no_dcs, cfg_ms_sup_no_dcs_cmd, dcs, "dcs", "DCS (1800)", 0);
1620 DEFUN(cfg_ms_sup_class_900, cfg_ms_sup_class_900_cmd, "class-900 (1|2|3|4|5)",
1621 "Select power class for GSM 850/900\n"
1628 struct osmocom_ms *ms = vty->index;
1629 struct gsm_settings *set = &ms->settings;
1630 struct gsm_support *sup = &ms->support;
1632 set->class_900 = atoi(argv[0]);
1634 if (set->class_900 < sup->class_900 && !vty_reading)
1635 vty_out(vty, "You selected an higher class than supported "
1636 " by hardware!%s", VTY_NEWLINE);
1641 DEFUN(cfg_ms_sup_class_dcs, cfg_ms_sup_class_dcs_cmd, "class-dcs (1|2|3)",
1642 "Select power class for DCS 1800\n"
1647 struct osmocom_ms *ms = vty->index;
1648 struct gsm_settings *set = &ms->settings;
1649 struct gsm_support *sup = &ms->support;
1651 set->class_dcs = atoi(argv[0]);
1653 if (((set->class_dcs + 1) & 3) < ((sup->class_dcs + 1) & 3)
1655 vty_out(vty, "You selected an higher class than supported "
1656 " by hardware!%s", VTY_NEWLINE);
1661 DEFUN(cfg_ms_sup_ch_cap, cfg_ms_sup_ch_cap_cmd, "channel-capability "
1662 "(sdcch|sdcch+tchf|sdcch+tchf+tchh)",
1663 "Select channel capability\nSDCCH only\nSDCCH + TCH/F\nSDCCH + TCH/H")
1665 struct osmocom_ms *ms = vty->index;
1666 struct gsm_settings *set = &ms->settings;
1667 struct gsm_support *sup = &ms->support;
1670 if (!strcmp(argv[0], "sdcch+tchf+tchh"))
1671 ch_cap = GSM_CAP_SDCCH_TCHF_TCHH;
1672 else if (!strcmp(argv[0], "sdcch+tchf"))
1673 ch_cap = GSM_CAP_SDCCH_TCHF;
1675 ch_cap = GSM_CAP_SDCCH;
1677 if (ch_cap > sup->ch_cap && !vty_reading) {
1678 vty_out(vty, "You selected an higher capability than supported "
1679 " by hardware!%s", VTY_NEWLINE);
1683 if (ch_cap != set->ch_cap
1684 && (ch_cap == GSM_CAP_SDCCH || set->ch_cap == GSM_CAP_SDCCH))
1687 set->ch_cap = ch_cap;
1692 SUP_EN(cfg_ms_sup_full_v1, cfg_ms_sup_full_v1_cmd, full_v1, "full-speech-v1",
1693 "Full rate speech V1", 0);
1694 SUP_DI(cfg_ms_sup_no_full_v1, cfg_ms_sup_no_full_v1_cmd, full_v1,
1695 "full-speech-v1", "Full rate speech V1", 0);
1696 SUP_EN(cfg_ms_sup_full_v2, cfg_ms_sup_full_v2_cmd, full_v2, "full-speech-v2",
1697 "Full rate speech V2 (EFR)", 0);
1698 SUP_DI(cfg_ms_sup_no_full_v2, cfg_ms_sup_no_full_v2_cmd, full_v2,
1699 "full-speech-v2", "Full rate speech V2 (EFR)", 0);
1700 SUP_EN(cfg_ms_sup_full_v3, cfg_ms_sup_full_v3_cmd, full_v3, "full-speech-v3",
1701 "Full rate speech V3 (AMR)", 0);
1702 SUP_DI(cfg_ms_sup_no_full_v3, cfg_ms_sup_no_full_v3_cmd, full_v3,
1703 "full-speech-v3", "Full rate speech V3 (AMR)", 0);
1704 SUP_EN(cfg_ms_sup_half_v1, cfg_ms_sup_half_v1_cmd, half_v1, "half-speech-v1",
1705 "Half rate speech V1", 0);
1706 SUP_DI(cfg_ms_sup_no_half_v1, cfg_ms_sup_no_half_v1_cmd, half_v1,
1707 "half-speech-v1", "Half rate speech V1", 0);
1708 SUP_EN(cfg_ms_sup_half_v3, cfg_ms_sup_half_v3_cmd, half_v3, "half-speech-v3",
1709 "Half rate speech V3 (AMR)", 0);
1710 SUP_DI(cfg_ms_sup_no_half_v3, cfg_ms_sup_no_half_v3_cmd, half_v3,
1711 "half-speech-v3", "Half rate speech V3 (AMR)", 0);
1713 DEFUN(cfg_ms_sup_min_rxlev, cfg_ms_sup_min_rxlev_cmd, "min-rxlev <-110--47>",
1714 "Set the minimum receive level to select a cell\n"
1715 "Minimum receive level from -110 dBm to -47 dBm")
1717 struct osmocom_ms *ms = vty->index;
1718 struct gsm_settings *set = &ms->settings;
1720 set->min_rxlev_db = atoi(argv[0]);
1725 DEFUN(cfg_ms_sup_dsc_max, cfg_ms_sup_dsc_max_cmd, "dsc-max <90-500>",
1726 "Set the maximum DSC value. Standard is 90. Increase to make mobile "
1727 "more reliable against bad RX signal. This increase the propability "
1728 "of missing a paging requests\n"
1729 "DSC initial and maximum value (standard is 90)")
1731 struct osmocom_ms *ms = vty->index;
1732 struct gsm_settings *set = &ms->settings;
1734 set->dsc_max = atoi(argv[0]);
1739 /* per testsim config */
1740 DEFUN(cfg_ms_testsim, cfg_ms_testsim_cmd, "test-sim",
1741 "Configure test SIM emulation")
1743 vty->node = TESTSIM_NODE;
1748 DEFUN(cfg_test_imsi, cfg_test_imsi_cmd, "imsi IMSI",
1749 "Set IMSI on test card\n15 digits IMSI")
1751 struct osmocom_ms *ms = vty->index;
1752 struct gsm_settings *set = &ms->settings;
1753 char *error = gsm_check_imsi(argv[0]);
1756 vty_out(vty, "%s%s", error, VTY_NEWLINE);
1760 strcpy(set->test_imsi, argv[0]);
1766 #define HEX_STR "\nByte as two digits hexadecimal"
1767 DEFUN(cfg_test_ki_xor, cfg_test_ki_xor_cmd, "ki xor HEX HEX HEX HEX HEX HEX "
1768 "HEX HEX HEX HEX HEX HEX",
1769 "Set Key (Kc) on test card\nUse XOR algorithm" HEX_STR HEX_STR HEX_STR
1770 HEX_STR HEX_STR HEX_STR HEX_STR HEX_STR HEX_STR HEX_STR HEX_STR HEX_STR)
1772 struct osmocom_ms *ms = vty->index;
1773 struct gsm_settings *set = &ms->settings;
1778 for (i = 0; i < 12; i++) {
1780 if (!strncmp(p, "0x", 2))
1782 if (strlen(p) != 2) {
1783 vty_out(vty, "Expecting two digits hex value (with or "
1784 "without 0x in front)%s", VTY_NEWLINE);
1787 ki[i] = strtoul(p, NULL, 16);
1790 set->test_ki_type = GSM_SIM_KEY_XOR;
1791 memcpy(set->test_ki, ki, 12);
1795 DEFUN(cfg_test_ki_comp128, cfg_test_ki_comp128_cmd, "ki comp128 HEX HEX HEX "
1796 "HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX",
1797 "Set Key (Kc) on test card\nUse XOR algorithm" HEX_STR HEX_STR HEX_STR
1798 HEX_STR HEX_STR HEX_STR HEX_STR HEX_STR HEX_STR HEX_STR HEX_STR HEX_STR
1799 HEX_STR HEX_STR HEX_STR HEX_STR)
1801 struct osmocom_ms *ms = vty->index;
1802 struct gsm_settings *set = &ms->settings;
1807 for (i = 0; i < 16; i++) {
1809 if (!strncmp(p, "0x", 2))
1811 if (strlen(p) != 2) {
1812 vty_out(vty, "Expecting two digits hex value (with or "
1813 "without 0x in front)%s", VTY_NEWLINE);
1816 ki[i] = strtoul(p, NULL, 16);
1819 set->test_ki_type = GSM_SIM_KEY_COMP128;
1820 memcpy(set->test_ki, ki, 16);
1824 DEFUN(cfg_test_barr, cfg_test_barr_cmd, "barred-access",
1825 "Allow access to barred cells")
1827 struct osmocom_ms *ms = vty->index;
1828 struct gsm_settings *set = &ms->settings;
1835 DEFUN(cfg_test_no_barr, cfg_test_no_barr_cmd, "no barred-access",
1836 NO_STR "Deny access to barred cells")
1838 struct osmocom_ms *ms = vty->index;
1839 struct gsm_settings *set = &ms->settings;
1846 DEFUN(cfg_test_no_rplmn, cfg_test_no_rplmn_cmd, "no rplmn",
1847 NO_STR "Unset Registered PLMN")
1849 struct osmocom_ms *ms = vty->index;
1850 struct gsm_settings *set = &ms->settings;
1852 set->test_rplmn_valid = 0;
1858 DEFUN(cfg_test_rplmn, cfg_test_rplmn_cmd, "rplmn MCC MNC",
1859 "Set Registered PLMN\nMobile Country Code\nMobile Network Code")
1861 struct osmocom_ms *ms = vty->index;
1862 struct gsm_settings *set = &ms->settings;
1863 uint16_t mcc = gsm_input_mcc((char *)argv[0]),
1864 mnc = gsm_input_mnc((char *)argv[1]);
1867 vty_out(vty, "Given MCC invalid%s", VTY_NEWLINE);
1871 vty_out(vty, "Given MNC invalid%s", VTY_NEWLINE);
1874 set->test_rplmn_valid = 1;
1875 set->test_rplmn_mcc = mcc;
1876 set->test_rplmn_mnc = mnc;
1882 DEFUN(cfg_test_hplmn, cfg_test_hplmn_cmd, "hplmn-search (everywhere|foreign-country)",
1883 "Set Home PLMN search mode\n"
1884 "Search for HPLMN when on any other network\n"
1885 "Search for HPLMN when in a different country")
1887 struct osmocom_ms *ms = vty->index;
1888 struct gsm_settings *set = &ms->settings;
1890 switch (argv[0][0]) {
1892 set->test_always = 1;
1895 set->test_always = 0;
1903 enum node_type ms_vty_go_parent(struct vty *vty)
1905 switch (vty->node) {
1907 vty->node = CONFIG_NODE;
1912 vty->node = MS_NODE;
1915 vty->node = CONFIG_NODE;
1921 /* Down vty node level. */
1922 gDEFUN(ournode_exit,
1923 ournode_exit_cmd, "exit", "Exit current mode and down to previous mode\n")
1925 switch (vty->node) {
1927 vty->node = CONFIG_NODE;
1932 vty->node = MS_NODE;
1940 /* End of configuration. */
1942 ournode_end_cmd, "end", "End current mode and change to enable mode.")
1944 switch (vty->node) {
1947 /* Nothing to do. */
1954 vty_config_unlock(vty);
1955 vty->node = ENABLE_NODE;
1957 vty->index_sub = NULL;
1965 #define SUP_NODE(item) \
1966 install_element(SUPPORT_NODE, &cfg_ms_sup_item_cmd);
1968 int ms_vty_init(void)
1970 install_element_ve(&show_ms_cmd);
1971 install_element_ve(&show_subscr_cmd);
1972 install_element_ve(&show_support_cmd);
1973 install_element_ve(&show_states_cmd);
1974 install_element_ve(&show_cell_cmd);
1975 install_element_ve(&show_cell_si_cmd);
1976 install_element_ve(&show_ba_cmd);
1977 install_element_ve(&show_forb_la_cmd);
1978 install_element_ve(&show_forb_plmn_cmd);
1979 install_element_ve(&monitor_network_cmd);
1980 install_element_ve(&no_monitor_network_cmd);
1982 install_element(ENABLE_NODE, &sim_test_cmd);
1983 install_element(ENABLE_NODE, &sim_reader_cmd);
1984 install_element(ENABLE_NODE, &sim_remove_cmd);
1985 install_element(ENABLE_NODE, &sim_pin_cmd);
1986 install_element(ENABLE_NODE, &sim_disable_pin_cmd);
1987 install_element(ENABLE_NODE, &sim_enable_pin_cmd);
1988 install_element(ENABLE_NODE, &sim_change_pin_cmd);
1989 install_element(ENABLE_NODE, &sim_unblock_pin_cmd);
1990 install_element(ENABLE_NODE, &sim_lai_cmd);
1991 install_element(ENABLE_NODE, &network_search_cmd);
1992 install_element(ENABLE_NODE, &network_show_cmd);
1993 install_element(ENABLE_NODE, &network_select_cmd);
1994 install_element(ENABLE_NODE, &call_cmd);
1995 install_element(ENABLE_NODE, &call_retr_cmd);
1996 install_element(ENABLE_NODE, &call_dtmf_cmd);
1998 install_element(CONFIG_NODE, &cfg_gps_device_cmd);
1999 install_element(CONFIG_NODE, &cfg_gps_baud_cmd);
2000 install_element(CONFIG_NODE, &cfg_gps_enable_cmd);
2001 install_element(CONFIG_NODE, &cfg_no_gps_enable_cmd);
2003 install_element(CONFIG_NODE, &cfg_ms_cmd);
2004 install_element(CONFIG_NODE, &ournode_end_cmd);
2005 install_node(&ms_node, config_write_ms);
2006 install_default(MS_NODE);
2007 install_element(MS_NODE, &ournode_exit_cmd);
2008 install_element(MS_NODE, &ournode_end_cmd);
2009 install_element(MS_NODE, &cfg_ms_sim_cmd);
2010 install_element(MS_NODE, &cfg_ms_mode_cmd);
2011 install_element(MS_NODE, &cfg_ms_imei_cmd);
2012 install_element(MS_NODE, &cfg_ms_imei_fixed_cmd);
2013 install_element(MS_NODE, &cfg_ms_imei_random_cmd);
2014 install_element(MS_NODE, &cfg_ms_no_emerg_imsi_cmd);
2015 install_element(MS_NODE, &cfg_ms_emerg_imsi_cmd);
2016 install_element(MS_NODE, &cfg_ms_cw_cmd);
2017 install_element(MS_NODE, &cfg_ms_no_cw_cmd);
2018 install_element(MS_NODE, &cfg_ms_auto_answer_cmd);
2019 install_element(MS_NODE, &cfg_ms_no_auto_answer_cmd);
2020 install_element(MS_NODE, &cfg_ms_clip_cmd);
2021 install_element(MS_NODE, &cfg_ms_clir_cmd);
2022 install_element(MS_NODE, &cfg_ms_no_clip_cmd);
2023 install_element(MS_NODE, &cfg_ms_no_clir_cmd);
2024 install_element(MS_NODE, &cfg_ms_tx_power_cmd);
2025 install_element(MS_NODE, &cfg_ms_tx_power_val_cmd);
2026 install_element(MS_NODE, &cfg_ms_sim_delay_cmd);
2027 install_element(MS_NODE, &cfg_ms_no_sim_delay_cmd);
2028 install_element(MS_NODE, &cfg_ms_stick_cmd);
2029 install_element(MS_NODE, &cfg_ms_no_stick_cmd);
2030 install_element(MS_NODE, &cfg_ms_lupd_cmd);
2031 install_element(MS_NODE, &cfg_ms_no_lupd_cmd);
2032 install_element(MS_NODE, &cfg_ms_codec_full_cmd);
2033 install_element(MS_NODE, &cfg_ms_codec_full_pref_cmd);
2034 install_element(MS_NODE, &cfg_ms_codec_half_cmd);
2035 install_element(MS_NODE, &cfg_ms_codec_half_pref_cmd);
2036 install_element(MS_NODE, &cfg_ms_no_codec_half_cmd);
2037 install_element(MS_NODE, &cfg_ms_abbrev_cmd);
2038 install_element(MS_NODE, &cfg_ms_no_abbrev_cmd);
2039 install_element(MS_NODE, &cfg_ms_testsim_cmd);
2040 install_element(MS_NODE, &cfg_ms_support_cmd);
2041 install_node(&support_node, config_write_dummy);
2042 install_default(SUPPORT_NODE);
2043 install_element(SUPPORT_NODE, &ournode_exit_cmd);
2044 install_element(SUPPORT_NODE, &ournode_end_cmd);
2045 install_element(SUPPORT_NODE, &cfg_ms_sup_dtmf_cmd);
2046 install_element(SUPPORT_NODE, &cfg_ms_sup_no_dtmf_cmd);
2047 install_element(SUPPORT_NODE, &cfg_ms_sup_sms_cmd);
2048 install_element(SUPPORT_NODE, &cfg_ms_sup_no_sms_cmd);
2049 install_element(SUPPORT_NODE, &cfg_ms_sup_a5_1_cmd);
2050 install_element(SUPPORT_NODE, &cfg_ms_sup_no_a5_1_cmd);
2051 install_element(SUPPORT_NODE, &cfg_ms_sup_a5_2_cmd);
2052 install_element(SUPPORT_NODE, &cfg_ms_sup_no_a5_2_cmd);
2053 install_element(SUPPORT_NODE, &cfg_ms_sup_a5_3_cmd);
2054 install_element(SUPPORT_NODE, &cfg_ms_sup_no_a5_3_cmd);
2055 install_element(SUPPORT_NODE, &cfg_ms_sup_a5_4_cmd);
2056 install_element(SUPPORT_NODE, &cfg_ms_sup_no_a5_4_cmd);
2057 install_element(SUPPORT_NODE, &cfg_ms_sup_a5_5_cmd);
2058 install_element(SUPPORT_NODE, &cfg_ms_sup_no_a5_5_cmd);
2059 install_element(SUPPORT_NODE, &cfg_ms_sup_a5_6_cmd);
2060 install_element(SUPPORT_NODE, &cfg_ms_sup_no_a5_6_cmd);
2061 install_element(SUPPORT_NODE, &cfg_ms_sup_a5_7_cmd);
2062 install_element(SUPPORT_NODE, &cfg_ms_sup_no_a5_7_cmd);
2063 install_element(SUPPORT_NODE, &cfg_ms_sup_p_gsm_cmd);
2064 install_element(SUPPORT_NODE, &cfg_ms_sup_no_p_gsm_cmd);
2065 install_element(SUPPORT_NODE, &cfg_ms_sup_e_gsm_cmd);
2066 install_element(SUPPORT_NODE, &cfg_ms_sup_no_e_gsm_cmd);
2067 install_element(SUPPORT_NODE, &cfg_ms_sup_r_gsm_cmd);
2068 install_element(SUPPORT_NODE, &cfg_ms_sup_no_r_gsm_cmd);
2069 install_element(SUPPORT_NODE, &cfg_ms_sup_dcs_cmd);
2070 install_element(SUPPORT_NODE, &cfg_ms_sup_no_dcs_cmd);
2071 install_element(SUPPORT_NODE, &cfg_ms_sup_class_900_cmd);
2072 install_element(SUPPORT_NODE, &cfg_ms_sup_class_dcs_cmd);
2073 install_element(SUPPORT_NODE, &cfg_ms_sup_ch_cap_cmd);
2074 install_element(SUPPORT_NODE, &cfg_ms_sup_full_v1_cmd);
2075 install_element(SUPPORT_NODE, &cfg_ms_sup_no_full_v1_cmd);
2076 install_element(SUPPORT_NODE, &cfg_ms_sup_full_v2_cmd);
2077 install_element(SUPPORT_NODE, &cfg_ms_sup_no_full_v2_cmd);
2078 install_element(SUPPORT_NODE, &cfg_ms_sup_full_v3_cmd);
2079 install_element(SUPPORT_NODE, &cfg_ms_sup_no_full_v3_cmd);
2080 install_element(SUPPORT_NODE, &cfg_ms_sup_half_v1_cmd);
2081 install_element(SUPPORT_NODE, &cfg_ms_sup_no_half_v1_cmd);
2082 install_element(SUPPORT_NODE, &cfg_ms_sup_half_v3_cmd);
2083 install_element(SUPPORT_NODE, &cfg_ms_sup_no_half_v3_cmd);
2084 install_element(SUPPORT_NODE, &cfg_ms_sup_min_rxlev_cmd);
2085 install_element(SUPPORT_NODE, &cfg_ms_sup_dsc_max_cmd);
2086 install_node(&testsim_node, config_write_dummy);
2087 install_default(TESTSIM_NODE);
2088 install_element(TESTSIM_NODE, &ournode_exit_cmd);
2089 install_element(TESTSIM_NODE, &ournode_end_cmd);
2090 install_element(TESTSIM_NODE, &cfg_test_imsi_cmd);
2091 install_element(TESTSIM_NODE, &cfg_test_ki_xor_cmd);
2092 install_element(TESTSIM_NODE, &cfg_test_ki_comp128_cmd);
2093 install_element(TESTSIM_NODE, &cfg_test_barr_cmd);
2094 install_element(TESTSIM_NODE, &cfg_test_no_barr_cmd);
2095 install_element(TESTSIM_NODE, &cfg_test_no_rplmn_cmd);
2096 install_element(TESTSIM_NODE, &cfg_test_rplmn_cmd);
2097 install_element(TESTSIM_NODE, &cfg_test_hplmn_cmd);
2102 void vty_notify(struct osmocom_ms *ms, const char *fmt, ...)
2104 struct telnet_connection *connection;
2110 va_start(args, fmt);
2111 vsnprintf(buffer, sizeof(buffer) - 1, fmt, args);
2112 buffer[sizeof(buffer) - 1] = '\0';
2119 llist_for_each_entry(connection, &active_connections, entry) {
2120 vty = connection->vty;
2124 vty_out(vty, "%s%% (MS %s)%s", VTY_NEWLINE, ms->name,
2128 if (buffer[strlen(buffer) - 1] == '\n') {
2129 buffer[strlen(buffer) - 1] = '\0';
2130 vty_out(vty, "%% %s%s", buffer, VTY_NEWLINE);
2131 buffer[strlen(buffer)] = '\n';
2133 vty_out(vty, "%% %s", buffer);