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 <osmocom/core/utils.h>
29 #include <osmocom/gsm/gsm48.h>
30 #include <osmocom/core/talloc.h>
31 #include <osmocom/core/signal.h>
33 #include <osmocom/bb/common/osmocom_data.h>
34 #include <osmocom/bb/common/networks.h>
35 #include <osmocom/bb/common/gps.h>
36 #include <osmocom/bb/mobile/mncc.h>
37 #include <osmocom/bb/mobile/transaction.h>
38 #include <osmocom/bb/mobile/vty.h>
39 #include <osmocom/bb/mobile/app_mobile.h>
40 #include <osmocom/vty/telnet_interface.h>
44 int mncc_call(struct osmocom_ms *ms, char *number);
45 int mncc_hangup(struct osmocom_ms *ms);
46 int mncc_answer(struct osmocom_ms *ms);
47 int mncc_hold(struct osmocom_ms *ms);
48 int mncc_retrieve(struct osmocom_ms *ms, int number);
49 int mncc_dtmf(struct osmocom_ms *ms, char *dtmf);
51 extern struct llist_head ms_list;
52 extern struct llist_head active_connections;
54 struct cmd_node ms_node = {
60 struct cmd_node testsim_node = {
66 struct cmd_node support_node = {
72 static void print_vty(void *priv, const char *fmt, ...)
75 struct vty *vty = priv;
79 vsnprintf(buffer, sizeof(buffer) - 1, fmt, args);
80 buffer[sizeof(buffer) - 1] = '\0';
84 if (buffer[strlen(buffer) - 1] == '\n') {
85 buffer[strlen(buffer) - 1] = '\0';
86 vty_out(vty, "%s%s", buffer, VTY_NEWLINE);
88 vty_out(vty, "%s", buffer);
92 int vty_check_number(struct vty *vty, const char *number)
96 for (i = 0; i < strlen(number); i++) {
97 /* allow international notation with + */
98 if (i == 0 && number[i] == '+')
100 if (!(number[i] >= '0' && number[i] <= '9')
103 && !(number[i] >= 'a' && number[i] <= 'c')) {
104 vty_out(vty, "Invalid digit '%c' of number!%s",
105 number[i], VTY_NEWLINE);
109 if (number[0] == '\0' || (number[0] == '+' && number[1] == '\0')) {
110 vty_out(vty, "Given number has no digits!%s", VTY_NEWLINE);
118 static int hide_default = 0;
120 static void vty_restart(struct vty *vty, struct osmocom_ms *ms)
124 if (ms->shutdown != 0)
126 vty_out(vty, "You must restart MS '%s' ('shutdown / no shutdown') for "
127 "change to take effect!%s", ms->name, VTY_NEWLINE);
130 static struct osmocom_ms *get_ms(const char *name, struct vty *vty)
132 struct osmocom_ms *ms;
134 llist_for_each_entry(ms, &ms_list, entity) {
135 if (!strcmp(ms->name, name)) {
137 vty_out(vty, "MS '%s' is admin down.%s", name,
144 vty_out(vty, "MS name '%s' does not exits.%s", name, VTY_NEWLINE);
149 static void gsm_ms_dump(struct osmocom_ms *ms, struct vty *vty)
151 struct gsm_settings *set = &ms->settings;
152 struct gsm_trans *trans;
156 service = ", radio is not started";
157 else if (ms->mmlayer.state == GSM48_MM_ST_MM_IDLE) {
158 /* current MM idle state */
159 switch (ms->mmlayer.substate) {
160 case GSM48_MM_SST_NORMAL_SERVICE:
161 case GSM48_MM_SST_PLMN_SEARCH_NORMAL:
162 service = ", service is normal";
164 case GSM48_MM_SST_LOC_UPD_NEEDED:
165 case GSM48_MM_SST_ATTEMPT_UPDATE:
166 service = ", service is limited (pending)";
168 case GSM48_MM_SST_NO_CELL_AVAIL:
169 service = ", service is unavailable";
172 if (ms->subscr.sim_valid)
173 service = ", service is limited";
175 service = ", service is limited "
180 service = ", MM connection active";
182 vty_out(vty, "MS '%s' is %s%s%s%s", ms->name,
183 (ms->shutdown) ? "administratively " : "",
184 (ms->shutdown || !ms->started) ? "down" : "up",
185 (!ms->shutdown) ? service : "",
187 vty_out(vty, " IMEI: %s%s", set->imei, VTY_NEWLINE);
188 vty_out(vty, " IMEISV: %s%s", set->imeisv, VTY_NEWLINE);
189 if (set->imei_random)
190 vty_out(vty, " IMEI generation: random (%d trailing "
191 "digits)%s", set->imei_random, VTY_NEWLINE);
193 vty_out(vty, " IMEI generation: fixed%s", VTY_NEWLINE);
198 if (set->plmn_mode == PLMN_MODE_AUTO)
199 vty_out(vty, " automatic network selection state: %s%s",
200 plmn_a_state_names[ms->plmn.state], VTY_NEWLINE);
202 vty_out(vty, " manual network selection state: %s%s",
203 plmn_m_state_names[ms->plmn.state], VTY_NEWLINE);
204 vty_out(vty, " cell selection state: %s",
205 cs_state_names[ms->cellsel.state]);
206 if (ms->rrlayer.state == GSM48_RR_ST_IDLE && ms->cellsel.selected)
207 vty_out(vty, " (ARFCN %s)",
208 gsm_print_arfcn(ms->cellsel.sel_arfcn));
209 vty_out(vty, "%s", VTY_NEWLINE);
210 vty_out(vty, " radio ressource layer state: %s%s",
211 gsm48_rr_state_names[ms->rrlayer.state], VTY_NEWLINE);
212 vty_out(vty, " mobility management layer state: %s",
213 gsm48_mm_state_names[ms->mmlayer.state]);
214 if (ms->mmlayer.state == GSM48_MM_ST_MM_IDLE)
216 gsm48_mm_substate_names[ms->mmlayer.substate]);
217 vty_out(vty, "%s", VTY_NEWLINE);
218 llist_for_each_entry(trans, &ms->trans_list, entry) {
219 vty_out(vty, " call control state: %s%s",
220 gsm48_cc_state_name(trans->cc.state), VTY_NEWLINE);
225 DEFUN(show_ms, show_ms_cmd, "show ms [MS_NAME]",
226 SHOW_STR "Display available MS entities\n")
228 struct osmocom_ms *ms;
231 llist_for_each_entry(ms, &ms_list, entity) {
232 if (!strcmp(ms->name, argv[0])) {
233 gsm_ms_dump(ms, vty);
237 vty_out(vty, "MS name '%s' does not exits.%s", argv[0],
241 llist_for_each_entry(ms, &ms_list, entity) {
242 gsm_ms_dump(ms, vty);
243 vty_out(vty, "%s", VTY_NEWLINE);
250 DEFUN(show_support, show_support_cmd, "show support [MS_NAME]",
251 SHOW_STR "Display information about MS support\n"
252 "Name of MS (see \"show ms\")")
254 struct osmocom_ms *ms;
257 ms = get_ms(argv[0], vty);
260 gsm_support_dump(ms, print_vty, vty);
262 llist_for_each_entry(ms, &ms_list, entity) {
263 gsm_support_dump(ms, print_vty, vty);
264 vty_out(vty, "%s", VTY_NEWLINE);
271 DEFUN(show_subscr, show_subscr_cmd, "show subscriber [MS_NAME]",
272 SHOW_STR "Display information about subscriber\n"
273 "Name of MS (see \"show ms\")")
275 struct osmocom_ms *ms;
278 ms = get_ms(argv[0], vty);
281 gsm_subscr_dump(&ms->subscr, print_vty, vty);
283 llist_for_each_entry(ms, &ms_list, entity) {
285 gsm_subscr_dump(&ms->subscr, print_vty, vty);
286 vty_out(vty, "%s", VTY_NEWLINE);
294 DEFUN(show_cell, show_cell_cmd, "show cell MS_NAME",
295 SHOW_STR "Display information about received cells\n"
296 "Name of MS (see \"show ms\")")
298 struct osmocom_ms *ms;
300 ms = get_ms(argv[0], vty);
304 gsm322_dump_cs_list(&ms->cellsel, GSM322_CS_FLAG_SYSINFO, print_vty,
310 DEFUN(show_cell_si, show_cell_si_cmd, "show cell MS_NAME <0-1023> [pcs]",
311 SHOW_STR "Display information about received cell\n"
312 "Name of MS (see \"show ms\")\nRadio frequency number\n"
313 "Given frequency is PCS band (1900) rather than DCS band.")
315 struct osmocom_ms *ms;
316 struct gsm48_sysinfo *s;
317 uint16_t arfcn = atoi(argv[1]);
319 ms = get_ms(argv[0], vty);
324 if (arfcn < 512 || arfcn > 810) {
325 vty_out(vty, "Given ARFCN not in PCS band%s",
332 s = ms->cellsel.list[arfcn2index(arfcn)].sysinfo;
334 vty_out(vty, "Given ARFCN '%s' has no sysinfo available%s",
335 argv[1], VTY_NEWLINE);
339 gsm48_sysinfo_dump(s, arfcn, print_vty, vty, ms->settings.freq_map);
344 DEFUN(show_ba, show_ba_cmd, "show ba MS_NAME [MCC] [MNC]",
345 SHOW_STR "Display information about band allocations\n"
346 "Name of MS (see \"show ms\")\nMobile Country Code\n"
347 "Mobile Network Code")
349 struct osmocom_ms *ms;
350 uint16_t mcc = 0, mnc = 0;
352 ms = get_ms(argv[0], vty);
357 mcc = gsm_input_mcc((char *)argv[1]);
358 mnc = gsm_input_mnc((char *)argv[2]);
360 vty_out(vty, "Given MCC invalid%s", VTY_NEWLINE);
364 vty_out(vty, "Given MNC invalid%s", VTY_NEWLINE);
369 gsm322_dump_ba_list(&ms->cellsel, mcc, mnc, print_vty, vty);
374 DEFUN(show_forb_plmn, show_forb_plmn_cmd, "show forbidden plmn MS_NAME",
375 SHOW_STR "Display information about forbidden cells / networks\n"
376 "Display forbidden PLMNs\nName of MS (see \"show ms\")")
378 struct osmocom_ms *ms;
380 ms = get_ms(argv[0], vty);
384 gsm_subscr_dump_forbidden_plmn(ms, print_vty, vty);
389 DEFUN(show_forb_la, show_forb_la_cmd, "show forbidden location-area MS_NAME",
390 SHOW_STR "Display information about forbidden cells / networks\n"
391 "Display forbidden location areas\nName of MS (see \"show ms\")")
393 struct osmocom_ms *ms;
395 ms = get_ms(argv[0], vty);
399 gsm322_dump_forbidden_la(ms, print_vty, vty);
404 DEFUN(monitor_network, monitor_network_cmd, "monitor network MS_NAME",
405 "Monitor...\nMonitor network information\nName of MS (see \"show ms\")")
407 struct osmocom_ms *ms;
409 ms = get_ms(argv[0], vty);
413 gsm48_rr_start_monitor(ms);
418 DEFUN(no_monitor_network, no_monitor_network_cmd, "no monitor network MS_NAME",
419 NO_STR "Monitor...\nDeactivate monitor of network information\n"
420 "Name of MS (see \"show ms\")")
422 struct osmocom_ms *ms;
424 ms = get_ms(argv[0], vty);
428 gsm48_rr_stop_monitor(ms);
433 DEFUN(sim_test, sim_test_cmd, "sim testcard MS_NAME [MCC] [MNC] [LAC] [TMSI]",
434 "SIM actions\nInsert test card\nName of MS (see \"show ms\")\n"
435 "Mobile Country Code of RPLMN\nMobile Network Code of RPLMN\n"
436 "Optionally locatio area code\nOptionally current assigned TMSI")
438 struct osmocom_ms *ms;
439 uint16_t mcc = 0x001, mnc = 0x01f, lac = 0x0000;
440 uint32_t tmsi = 0xffffffff;
442 ms = get_ms(argv[0], vty);
446 if (ms->subscr.sim_valid) {
447 vty_out(vty, "SIM already presend, remove first!%s",
453 mcc = gsm_input_mcc((char *)argv[1]);
454 mnc = gsm_input_mnc((char *)argv[2]);
456 vty_out(vty, "Given MCC invalid%s", VTY_NEWLINE);
460 vty_out(vty, "Given MNC invalid%s", VTY_NEWLINE);
466 lac = strtoul(argv[3], NULL, 16);
469 tmsi = strtoul(argv[4], NULL, 16);
471 gsm_subscr_testcard(ms, mcc, mnc, lac, tmsi);
476 DEFUN(sim_reader, sim_reader_cmd, "sim reader MS_NAME",
477 "SIM actions\nSelect SIM from reader\nName of MS (see \"show ms\")")
479 struct osmocom_ms *ms;
481 ms = get_ms(argv[0], vty);
485 if (ms->subscr.sim_valid) {
486 vty_out(vty, "SIM already presend, remove first!%s",
491 gsm_subscr_simcard(ms);
496 DEFUN(sim_remove, sim_remove_cmd, "sim remove MS_NAME",
497 "SIM actions\nRemove SIM card\nName of MS (see \"show ms\")")
499 struct osmocom_ms *ms;
501 ms = get_ms(argv[0], vty);
505 if (!ms->subscr.sim_valid) {
506 vty_out(vty, "No Sim inserted!%s", VTY_NEWLINE);
510 gsm_subscr_remove(ms);
515 DEFUN(sim_pin, sim_pin_cmd, "sim pin MS_NAME PIN",
516 "SIM actions\nEnter PIN for SIM card\nName of MS (see \"show ms\")\n"
519 struct osmocom_ms *ms;
521 ms = get_ms(argv[0], vty);
525 if (strlen(argv[1]) < 4 || strlen(argv[1]) > 8) {
526 vty_out(vty, "PIN must be in range 4..8!%s", VTY_NEWLINE);
530 if (!ms->subscr.sim_pin_required) {
531 vty_out(vty, "No PIN is required at this time!%s", VTY_NEWLINE);
535 gsm_subscr_sim_pin(ms, (char *)argv[1], "", 0);
540 DEFUN(sim_disable_pin, sim_disable_pin_cmd, "sim disable-pin MS_NAME PIN",
541 "SIM actions\nDisable PIN of SIM card\nName of MS (see \"show ms\")\n"
544 struct osmocom_ms *ms;
546 ms = get_ms(argv[0], vty);
550 if (strlen(argv[1]) < 4 || strlen(argv[1]) > 8) {
551 vty_out(vty, "PIN must be in range 4..8!%s", VTY_NEWLINE);
555 gsm_subscr_sim_pin(ms, (char *)argv[1], "", -1);
560 DEFUN(sim_enable_pin, sim_enable_pin_cmd, "sim enable-pin MS_NAME PIN",
561 "SIM actions\nEnable PIN of SIM card\nName of MS (see \"show ms\")\n"
564 struct osmocom_ms *ms;
566 ms = get_ms(argv[0], vty);
570 if (strlen(argv[1]) < 4 || strlen(argv[1]) > 8) {
571 vty_out(vty, "PIN must be in range 4..8!%s", VTY_NEWLINE);
575 gsm_subscr_sim_pin(ms, (char *)argv[1], "", 1);
580 DEFUN(sim_change_pin, sim_change_pin_cmd, "sim change-pin MS_NAME OLD NEW",
581 "SIM actions\nChange PIN of SIM card\nName of MS (see \"show ms\")\n"
582 "Old PIN number\nNew PIN number")
584 struct osmocom_ms *ms;
586 ms = get_ms(argv[0], vty);
590 if (strlen(argv[1]) < 4 || strlen(argv[1]) > 8) {
591 vty_out(vty, "Old PIN must be in range 4..8!%s", VTY_NEWLINE);
594 if (strlen(argv[2]) < 4 || strlen(argv[2]) > 8) {
595 vty_out(vty, "New PIN must be in range 4..8!%s", VTY_NEWLINE);
599 gsm_subscr_sim_pin(ms, (char *)argv[1], (char *)argv[2], 2);
604 DEFUN(sim_unblock_pin, sim_unblock_pin_cmd, "sim unblock-pin MS_NAME PUC NEW",
605 "SIM actions\nChange PIN of SIM card\nName of MS (see \"show ms\")\n"
606 "Personal Unblock Key\nNew PIN number")
608 struct osmocom_ms *ms;
610 ms = get_ms(argv[0], vty);
614 if (strlen(argv[1]) != 8) {
615 vty_out(vty, "PUC must be 8 digits!%s", VTY_NEWLINE);
618 if (strlen(argv[2]) < 4 || strlen(argv[2]) > 8) {
619 vty_out(vty, "PIN must be in range 4..8!%s", VTY_NEWLINE);
623 gsm_subscr_sim_pin(ms, (char *)argv[1], (char *)argv[2], 99);
628 DEFUN(sim_lai, sim_lai_cmd, "sim lai MS_NAME MCC MNC LAC",
629 "SIM actions\nChange LAI of SIM card\nName of MS (see \"show ms\")\n"
630 "Mobile Country Code\nMobile Network Code\nLocation Area Code "
631 " (use 0000 to remove LAI)")
633 struct osmocom_ms *ms;
634 uint16_t mcc = gsm_input_mcc((char *)argv[1]),
635 mnc = gsm_input_mnc((char *)argv[2]),
636 lac = strtoul(argv[3], NULL, 16);
638 ms = get_ms(argv[0], vty);
643 vty_out(vty, "Given MCC invalid%s", VTY_NEWLINE);
647 vty_out(vty, "Given MNC invalid%s", VTY_NEWLINE);
651 ms->subscr.mcc = mcc;
652 ms->subscr.mnc = mnc;
653 ms->subscr.lac = lac;
654 ms->subscr.tmsi = 0xffffffff;
656 gsm_subscr_write_loci(ms);
661 DEFUN(network_select, network_select_cmd, "network select MS_NAME MCC MNC",
662 "Select ...\nSelect Network\nName of MS (see \"show ms\")\n"
663 "Mobile Country Code\nMobile Network Code")
665 struct osmocom_ms *ms;
666 struct gsm322_plmn *plmn;
668 struct gsm322_msg *ngm;
669 struct gsm322_plmn_list *temp;
670 uint16_t mcc = gsm_input_mcc((char *)argv[1]),
671 mnc = gsm_input_mnc((char *)argv[2]);
674 ms = get_ms(argv[0], vty);
680 vty_out(vty, "Given MCC invalid%s", VTY_NEWLINE);
684 vty_out(vty, "Given MNC invalid%s", VTY_NEWLINE);
688 llist_for_each_entry(temp, &plmn->sorted_plmn, entry)
689 if (temp->mcc == mcc && temp->mnc == mnc)
692 vty_out(vty, "Network not in list!%s", VTY_NEWLINE);
696 nmsg = gsm322_msgb_alloc(GSM322_EVENT_CHOOSE_PLMN);
699 ngm = (struct gsm322_msg *) nmsg->data;
702 gsm322_plmn_sendmsg(ms, nmsg);
707 DEFUN(call, call_cmd, "call MS_NAME (NUMBER|emergency|answer|hangup|hold)",
708 "Make a call\nName of MS (see \"show ms\")\nPhone number to call "
709 "(Use digits '0123456789*#abc', and '+' to dial international)\n"
710 "Make an emergency call\nAnswer an incomming call\nHangup a call\n"
711 "Hold current active call\n")
713 struct osmocom_ms *ms;
714 struct gsm_settings *set;
715 struct gsm_settings_abbrev *abbrev;
718 ms = get_ms(argv[0], vty);
723 if (set->ch_cap == GSM_CAP_SDCCH) {
724 vty_out(vty, "Basic call is not supported for SDCCH only "
725 "mobile%s", VTY_NEWLINE);
729 number = (char *)argv[1];
730 if (!strcmp(number, "emergency"))
731 mncc_call(ms, number);
732 else if (!strcmp(number, "answer"))
734 else if (!strcmp(number, "hangup"))
736 else if (!strcmp(number, "hold"))
739 llist_for_each_entry(abbrev, &set->abbrev, list) {
740 if (!strcmp(number, abbrev->abbrev)) {
741 number = abbrev->number;
742 vty_out(vty, "Dialing number '%s'%s", number,
747 if (vty_check_number(vty, number))
749 mncc_call(ms, number);
755 DEFUN(call_retr, call_retr_cmd, "call MS_NAME retrieve [NUMBER]",
756 "Make a call\nName of MS (see \"show ms\")\n"
757 "Retrieve call on hold\nNumber of call to retrieve")
759 struct osmocom_ms *ms;
761 ms = get_ms(argv[0], vty);
765 mncc_retrieve(ms, (argc > 1) ? atoi(argv[1]) : 0);
770 DEFUN(call_dtmf, call_dtmf_cmd, "call MS_NAME dtmf DIGITS",
771 "Make a call\nName of MS (see \"show ms\")\n"
772 "One or more DTMF digits to transmit")
774 struct osmocom_ms *ms;
775 struct gsm_settings *set;
777 ms = get_ms(argv[0], vty);
783 vty_out(vty, "DTMF not supported, please enable!%s",
788 mncc_dtmf(ms, (char *)argv[1]);
793 DEFUN(network_show, network_show_cmd, "network show MS_NAME",
794 "Network ...\nShow results of network search (again)\n"
795 "Name of MS (see \"show ms\")")
797 struct osmocom_ms *ms;
798 struct gsm_settings *set;
799 struct gsm322_plmn *plmn;
800 struct gsm322_plmn_list *temp;
802 ms = get_ms(argv[0], vty);
808 if (set->plmn_mode != PLMN_MODE_AUTO
809 && plmn->state != GSM322_M3_NOT_ON_PLMN) {
810 vty_out(vty, "Start network search first!%s", VTY_NEWLINE);
814 llist_for_each_entry(temp, &plmn->sorted_plmn, entry)
815 vty_out(vty, " Network %s, %s (%s, %s)%s",
816 gsm_print_mcc(temp->mcc), gsm_print_mnc(temp->mnc),
817 gsm_get_mcc(temp->mcc),
818 gsm_get_mnc(temp->mcc, temp->mnc), VTY_NEWLINE);
823 DEFUN(network_search, network_search_cmd, "network search MS_NAME",
824 "Network ...\nTrigger network search\nName of MS (see \"show ms\")")
826 struct osmocom_ms *ms;
829 ms = get_ms(argv[0], vty);
833 nmsg = gsm322_msgb_alloc(GSM322_EVENT_USER_RESEL);
836 gsm322_plmn_sendmsg(ms, nmsg);
841 DEFUN(cfg_gps_enable, cfg_gps_enable_cmd, "gps enable",
844 if (osmo_gps_open()) {
846 vty_out(vty, "Failed to open GPS device!%s", VTY_NEWLINE);
854 DEFUN(cfg_no_gps_enable, cfg_no_gps_enable_cmd, "no gps enable",
855 NO_STR "Disable GPS receiver")
865 DEFUN(cfg_gps_host, cfg_gps_host_cmd, "gps host HOST:PORT",
866 "GPS receiver\nSelect gpsd host and port\n"
867 "IP and port (optional) of the host running gpsd")
869 char* colon = strstr(argv[0], ":");
871 memcpy(g.gpsd_host, argv[0], colon - argv[0] - 1);
872 g.gpsd_host[colon - argv[0]] = '\0';
873 memcpy(g.gpsd_port, colon, strlen(colon));
874 g.gpsd_port[strlen(colon)] = '\0';
876 snprintf(g.gpsd_host, ARRAY_SIZE(g.gpsd_host), "%s", argv[0]);
877 g.gpsd_host[ARRAY_SIZE(g.gpsd_host) - 1] = '\0';
878 snprintf(g.gpsd_port, ARRAY_SIZE(g.gpsd_port), "2947");
879 g.gpsd_port[ARRAY_SIZE(g.gpsd_port) - 1] = '\0';
881 g.gps_type = GPS_TYPE_GPSD;
884 if (osmo_gps_open()) {
885 vty_out(vty, "Failed to connect to gpsd host!%s",
895 DEFUN(cfg_gps_device, cfg_gps_device_cmd, "gps device DEVICE",
896 "GPS receiver\nSelect serial device\n"
897 "Full path of serial device including /dev/")
899 strncpy(g.device, argv[0], sizeof(g.device));
900 g.device[sizeof(g.device) - 1] = '\0';
901 g.gps_type = GPS_TYPE_SERIAL;
904 if (osmo_gps_open()) {
905 vty_out(vty, "Failed to open GPS device!%s",
914 DEFUN(cfg_gps_baud, cfg_gps_baud_cmd, "gps baudrate "
915 "(default|4800|""9600|19200|38400|57600|115200)",
916 "GPS receiver\nSelect baud rate\nDefault, don't modify\n\n\n\n\n\n")
918 if (argv[0][0] == 'd')
921 g.baud = atoi(argv[0]);
924 if (osmo_gps_open()) {
926 vty_out(vty, "Failed to open GPS device!%s",
935 DEFUN(cfg_hide_default, cfg_hide_default_cmd, "hide-default",
936 "Hide most default values in config to make it more compact")
943 DEFUN(cfg_no_hide_default, cfg_no_hide_default_cmd, "no hide-default",
944 NO_STR "Show default values in config")
952 DEFUN(cfg_ms, cfg_ms_cmd, "ms MS_NAME",
953 "Select a mobile station to configure\nName of MS (see \"show ms\")")
955 struct osmocom_ms *ms;
958 llist_for_each_entry(ms, &ms_list, entity) {
959 if (!strcmp(ms->name, argv[0])) {
967 vty_out(vty, "MS name '%s' does not exits, try "
968 "'ms %s create'%s", argv[0], argv[0],
972 ms = mobile_new((char *)argv[0]);
974 vty_out(vty, "Failed to add MS name '%s'%s", argv[0],
986 DEFUN(cfg_ms_create, cfg_ms_create_cmd, "ms MS_NAME create",
987 "Select a mobile station to configure\nName of MS (see \"show ms\")\n"
988 "Create if MS does not exists")
990 struct osmocom_ms *ms;
993 llist_for_each_entry(ms, &ms_list, entity) {
994 if (!strcmp(ms->name, argv[0])) {
1001 ms = mobile_new((char *)argv[0]);
1003 vty_out(vty, "Failed to add MS name '%s'%s", argv[0],
1010 vty->node = MS_NODE;
1012 vty_out(vty, "MS '%s' created, after configuration, do 'no shutdown'%s",
1013 argv[0], VTY_NEWLINE);
1017 DEFUN(cfg_ms_rename, cfg_ms_rename_cmd, "ms MS_NAME rename MS_NAME",
1018 "Select a mobile station to configure\nName of MS (see \"show ms\")\n"
1019 "Rename MS\nNew name of MS")
1021 struct osmocom_ms *ms;
1024 llist_for_each_entry(ms, &ms_list, entity) {
1025 if (!strcmp(ms->name, argv[0])) {
1032 vty_out(vty, "MS name '%s' does not exist%s", argv[0],
1037 strncpy(ms->name, argv[1], sizeof(ms->name) - 1);
1042 DEFUN(cfg_no_ms, cfg_no_ms_cmd, "no ms MS_NAME",
1043 NO_STR "Select a mobile station to remove\n"
1044 "Name of MS (see \"show ms\")")
1046 struct osmocom_ms *ms;
1049 llist_for_each_entry(ms, &ms_list, entity) {
1050 if (!strcmp(ms->name, argv[0])) {
1057 vty_out(vty, "MS name '%s' does not exist%s", argv[0],
1062 mobile_delete(ms, 1);
1067 #define SUP_WRITE(item, cmd) \
1069 if (!hide_default || !set->item) \
1070 vty_out(vty, " %s%s%s", (set->item) ? "" : "no ", \
1073 static void config_write_ms(struct vty *vty, struct osmocom_ms *ms)
1075 struct gsm_settings *set = &ms->settings;
1076 struct gsm_support *sup = &ms->support;
1077 struct gsm_settings_abbrev *abbrev;
1079 vty_out(vty, "ms %s%s", ms->name, VTY_NEWLINE);
1080 vty_out(vty, " layer2-socket %s%s", set->layer2_socket_path,
1082 vty_out(vty, " sap-socket %s%s", set->sap_socket_path, VTY_NEWLINE);
1083 switch(set->sim_type) {
1084 case GSM_SIM_TYPE_NONE:
1085 vty_out(vty, " sim none%s", VTY_NEWLINE);
1087 case GSM_SIM_TYPE_READER:
1088 vty_out(vty, " sim reader%s", VTY_NEWLINE);
1090 case GSM_SIM_TYPE_TEST:
1091 vty_out(vty, " sim test%s", VTY_NEWLINE);
1094 vty_out(vty, " network-selection-mode %s%s", (set->plmn_mode
1095 == PLMN_MODE_AUTO) ? "auto" : "manual", VTY_NEWLINE);
1096 vty_out(vty, " imei %s %s%s", set->imei,
1097 set->imeisv + strlen(set->imei), VTY_NEWLINE);
1098 if (set->imei_random)
1099 vty_out(vty, " imei-random %d%s", set->imei_random,
1103 vty_out(vty, " imei-fixed%s", VTY_NEWLINE);
1104 if (set->emergency_imsi[0])
1105 vty_out(vty, " emergency-imsi %s%s", set->emergency_imsi,
1109 vty_out(vty, " no emergency-imsi%s", VTY_NEWLINE);
1110 if (!hide_default || set->cw)
1111 vty_out(vty, " %scall-waiting%s", (set->cw) ? "" : "no ",
1113 if (!hide_default || set->auto_answer)
1114 vty_out(vty, " %sauto-answer%s",
1115 (set->auto_answer) ? "" : "no ", VTY_NEWLINE);
1116 if (!hide_default || set->clip)
1117 vty_out(vty, " %sclip%s", (set->clip) ? "" : "no ",
1119 if (!hide_default || set->clir)
1120 vty_out(vty, " %sclir%s", (set->clir) ? "" : "no ",
1122 if (set->alter_tx_power)
1123 if (set->alter_tx_power_value)
1124 vty_out(vty, " tx-power %d%s",
1125 set->alter_tx_power_value, VTY_NEWLINE);
1127 vty_out(vty, " tx-power full%s", VTY_NEWLINE);
1130 vty_out(vty, " tx-power auto%s", VTY_NEWLINE);
1131 if (set->alter_delay)
1132 vty_out(vty, " simulated-delay %d%s", set->alter_delay,
1136 vty_out(vty, " no simulated-delay%s", VTY_NEWLINE);
1138 vty_out(vty, " stick %d%s%s", set->stick_arfcn & 1023,
1139 (set->stick_arfcn & ARFCN_PCS) ? " pcs" : "",
1143 vty_out(vty, " no stick%s", VTY_NEWLINE);
1144 if (!hide_default || set->no_lupd)
1145 vty_out(vty, " %slocation-updating%s",
1146 (set->no_lupd) ? "no " : "", VTY_NEWLINE);
1147 if (set->full_v1 || set->full_v2 || set->full_v3) {
1148 /* mandatory anyway */
1149 vty_out(vty, " codec full-speed%s%s",
1150 (!set->half_prefer) ? " prefer" : "",
1153 if (set->half_v1 || set->half_v3) {
1155 vty_out(vty, " codec half-speed%s%s",
1156 (set->half_prefer) ? " prefer" : "",
1159 vty_out(vty, " no codec half-speed%s", VTY_NEWLINE);
1161 if (llist_empty(&set->abbrev)) {
1163 vty_out(vty, " no abbrev%s", VTY_NEWLINE);
1165 llist_for_each_entry(abbrev, &set->abbrev, list)
1166 vty_out(vty, " abbrev %s %s%s%s%s", abbrev->abbrev,
1167 abbrev->number, (abbrev->name[0]) ? " " : "",
1168 abbrev->name, VTY_NEWLINE);
1170 vty_out(vty, " support%s", VTY_NEWLINE);
1171 SUP_WRITE(sms_ptp, "sms");
1172 SUP_WRITE(a5_1, "a5/1");
1173 SUP_WRITE(a5_2, "a5/2");
1174 SUP_WRITE(a5_3, "a5/3");
1175 SUP_WRITE(a5_4, "a5/4");
1176 SUP_WRITE(a5_5, "a5/5");
1177 SUP_WRITE(a5_6, "a5/6");
1178 SUP_WRITE(a5_7, "a5/7");
1179 SUP_WRITE(p_gsm, "p-gsm");
1180 SUP_WRITE(e_gsm, "e-gsm");
1181 SUP_WRITE(r_gsm, "r-gsm");
1182 SUP_WRITE(pcs, "gsm-850");
1183 SUP_WRITE(gsm_480, "gsm-480");
1184 SUP_WRITE(gsm_450, "gsm-450");
1185 SUP_WRITE(dcs, "dcs");
1186 SUP_WRITE(pcs, "pcs");
1187 if (sup->r_gsm || sup->e_gsm || sup->p_gsm)
1188 if (!hide_default || sup->class_900 != set->class_900)
1189 vty_out(vty, " class-900 %d%s", set->class_900,
1192 if (!hide_default || sup->class_850 != set->class_850)
1193 vty_out(vty, " class-850 %d%s", set->class_850,
1195 if (sup->gsm_480 || sup->gsm_450)
1196 if (!hide_default || sup->class_400 != set->class_400)
1197 vty_out(vty, " class-400 %d%s", set->class_400,
1200 if (!hide_default || sup->class_dcs != set->class_dcs)
1201 vty_out(vty, " class-dcs %d%s", set->class_dcs,
1204 if (!hide_default || sup->class_pcs != set->class_pcs)
1205 vty_out(vty, " class-pcs %d%s", set->class_pcs,
1207 if (!hide_default || sup->ch_cap != set->ch_cap) {
1208 switch (set->ch_cap) {
1210 vty_out(vty, " channel-capability sdcch%s",
1213 case GSM_CAP_SDCCH_TCHF:
1214 vty_out(vty, " channel-capability sdcch+tchf%s",
1217 case GSM_CAP_SDCCH_TCHF_TCHH:
1218 vty_out(vty, " channel-capability sdcch+tchf+tchh%s",
1223 SUP_WRITE(full_v1, "full-speech-v1");
1224 SUP_WRITE(full_v2, "full-speech-v2");
1225 SUP_WRITE(full_v3, "full-speech-v3");
1226 SUP_WRITE(half_v1, "half-speech-v1");
1227 SUP_WRITE(half_v3, "half-speech-v3");
1228 if (!hide_default || sup->min_rxlev_db != set->min_rxlev_db)
1229 vty_out(vty, " min-rxlev %d%s", set->min_rxlev_db,
1231 if (!hide_default || sup->dsc_max != set->dsc_max)
1232 vty_out(vty, " dsc-max %d%s", set->dsc_max, VTY_NEWLINE);
1233 vty_out(vty, " exit%s", VTY_NEWLINE);
1234 vty_out(vty, " test-sim%s", VTY_NEWLINE);
1235 vty_out(vty, " imsi %s%s", set->test_imsi, VTY_NEWLINE);
1236 switch (set->test_ki_type) {
1237 case GSM_SIM_KEY_XOR:
1238 vty_out(vty, " ki xor %s%s",
1239 osmo_hexdump(set->test_ki, 12), VTY_NEWLINE);
1241 case GSM_SIM_KEY_COMP128:
1242 vty_out(vty, " ki comp128 %s%s",
1243 osmo_hexdump(set->test_ki, 16), VTY_NEWLINE);
1246 if (!hide_default || set->test_barr)
1247 vty_out(vty, " %sbarred-access%s",
1248 (set->test_barr) ? "" : "no ", VTY_NEWLINE);
1249 if (set->test_rplmn_valid) {
1250 vty_out(vty, " rplmn %s %s",
1251 gsm_print_mcc(set->test_rplmn_mcc),
1252 gsm_print_mnc(set->test_rplmn_mnc));
1253 if (set->test_lac > 0x0000 && set->test_lac < 0xfffe)
1254 vty_out(vty, " 0x%04x", set->test_lac);
1255 if (set->test_tmsi != 0xffffffff)
1256 vty_out(vty, " 0x%08x", set->test_tmsi);
1257 vty_out(vty, "%s", VTY_NEWLINE);
1260 vty_out(vty, " no rplmn%s", VTY_NEWLINE);
1261 if (!hide_default || set->test_always)
1262 vty_out(vty, " hplmn-search %s%s",
1263 (set->test_always) ? "everywhere" : "foreign-country",
1265 vty_out(vty, " exit%s", VTY_NEWLINE);
1266 /* no shutdown must be written to config, because shutdown is default */
1267 vty_out(vty, " %sshutdown%s", (ms->shutdown) ? "" : "no ",
1269 vty_out(vty, "exit%s", VTY_NEWLINE);
1270 vty_out(vty, "!%s", VTY_NEWLINE);
1273 static int config_write(struct vty *vty)
1275 struct osmocom_ms *ms;
1278 vty_out(vty, "gpsd host %s%s", g.gpsd_host, VTY_NEWLINE);
1279 vty_out(vty, "gpsd port %s%s", g.gpsd_port, VTY_NEWLINE);
1281 vty_out(vty, "gps device %s%s", g.device, VTY_NEWLINE);
1283 vty_out(vty, "gps baudrate %d%s", g.baud, VTY_NEWLINE);
1285 vty_out(vty, "gps baudrate default%s", VTY_NEWLINE);
1286 vty_out(vty, "%sgps enable%s", (g.enable) ? "" : "no ", VTY_NEWLINE);
1287 vty_out(vty, "!%s", VTY_NEWLINE);
1289 vty_out(vty, "%shide-default%s", (hide_default) ? "": "no ",
1291 vty_out(vty, "!%s", VTY_NEWLINE);
1293 llist_for_each_entry(ms, &ms_list, entity)
1294 config_write_ms(vty, ms);
1299 DEFUN(cfg_ms_show_this, cfg_ms_show_this_cmd, "show this",
1300 SHOW_STR "Show config of this MS")
1302 struct osmocom_ms *ms = vty->index;
1304 config_write_ms(vty, ms);
1309 DEFUN(cfg_ms_layer2, cfg_ms_layer2_cmd, "layer2-socket PATH",
1310 "Define socket path to connect between layer 2 and layer 1\n"
1311 "Unix socket, default '/tmp/osmocom_l2'")
1313 struct osmocom_ms *ms = vty->index;
1314 struct gsm_settings *set = &ms->settings;
1316 strncpy(set->layer2_socket_path, argv[0],
1317 sizeof(set->layer2_socket_path) - 1);
1319 vty_restart(vty, ms);
1323 DEFUN(cfg_ms_sap, cfg_ms_sap_cmd, "sap-socket PATH",
1324 "Define socket path to connect to SIM reader\n"
1325 "Unix socket, default '/tmp/osmocom_sap'")
1327 struct osmocom_ms *ms = vty->index;
1328 struct gsm_settings *set = &ms->settings;
1330 strncpy(set->sap_socket_path, argv[0],
1331 sizeof(set->sap_socket_path) - 1);
1333 vty_restart(vty, ms);
1337 DEFUN(cfg_ms_sim, cfg_ms_sim_cmd, "sim (none|reader|test)",
1338 "Set SIM card type when powering on\nNo SIM interted\n"
1339 "Use SIM from reader\nTest SIM inserted")
1341 struct osmocom_ms *ms = vty->index;
1342 struct gsm_settings *set = &ms->settings;
1344 switch (argv[0][0]) {
1346 set->sim_type = GSM_SIM_TYPE_NONE;
1349 set->sim_type = GSM_SIM_TYPE_READER;
1352 set->sim_type = GSM_SIM_TYPE_TEST;
1355 vty_out(vty, "unknown SIM type%s", VTY_NEWLINE);
1359 vty_restart(vty, ms);
1363 DEFUN(cfg_ms_mode, cfg_ms_mode_cmd, "network-selection-mode (auto|manual)",
1364 "Set network selection mode\nAutomatic network selection\n"
1365 "Manual network selection")
1367 struct osmocom_ms *ms = vty->index;
1368 struct gsm_settings *set = &ms->settings;
1371 if (!ms->plmn.state) {
1372 if (argv[0][0] == 'a')
1373 set->plmn_mode = PLMN_MODE_AUTO;
1375 set->plmn_mode = PLMN_MODE_MANUAL;
1379 if (argv[0][0] == 'a')
1380 nmsg = gsm322_msgb_alloc(GSM322_EVENT_SEL_AUTO);
1382 nmsg = gsm322_msgb_alloc(GSM322_EVENT_SEL_MANUAL);
1385 gsm322_plmn_sendmsg(ms, nmsg);
1390 DEFUN(cfg_ms_imei, cfg_ms_imei_cmd, "imei IMEI [SV]",
1391 "Set IMEI (enter without control digit)\n15 Digits IMEI\n"
1392 "Software version digit")
1394 struct osmocom_ms *ms = vty->index;
1395 struct gsm_settings *set = &ms->settings;
1396 char *error, *sv = "0";
1399 sv = (char *)argv[1];
1401 error = gsm_check_imei(argv[0], sv);
1403 vty_out(vty, "%s%s", error, VTY_NEWLINE);
1407 strcpy(set->imei, argv[0]);
1408 strcpy(set->imeisv, argv[0]);
1409 strcpy(set->imeisv + 15, sv);
1414 DEFUN(cfg_ms_imei_fixed, cfg_ms_imei_fixed_cmd, "imei-fixed",
1415 "Use fixed IMEI on every power on")
1417 struct osmocom_ms *ms = vty->index;
1418 struct gsm_settings *set = &ms->settings;
1420 set->imei_random = 0;
1422 vty_restart(vty, ms);
1426 DEFUN(cfg_ms_imei_random, cfg_ms_imei_random_cmd, "imei-random <0-15>",
1427 "Use random IMEI on every power on\n"
1428 "Number of trailing digits to randomize")
1430 struct osmocom_ms *ms = vty->index;
1431 struct gsm_settings *set = &ms->settings;
1433 set->imei_random = atoi(argv[0]);
1435 vty_restart(vty, ms);
1439 DEFUN(cfg_ms_emerg_imsi, cfg_ms_emerg_imsi_cmd, "emergency-imsi IMSI",
1440 "Use special IMSI for emergency calls\n15 digits IMSI")
1442 struct osmocom_ms *ms = vty->index;
1443 struct gsm_settings *set = &ms->settings;
1446 error = gsm_check_imsi(argv[0]);
1448 vty_out(vty, "%s%s", error, VTY_NEWLINE);
1451 strcpy(set->emergency_imsi, argv[0]);
1456 DEFUN(cfg_ms_no_emerg_imsi, cfg_ms_no_emerg_imsi_cmd, "no emergency-imsi",
1457 NO_STR "Use IMSI of SIM or IMEI for emergency calls")
1459 struct osmocom_ms *ms = vty->index;
1460 struct gsm_settings *set = &ms->settings;
1462 set->emergency_imsi[0] = '\0';
1467 DEFUN(cfg_no_cw, cfg_ms_no_cw_cmd, "no call-waiting",
1468 NO_STR "Disallow waiting calls")
1470 struct osmocom_ms *ms = vty->index;
1471 struct gsm_settings *set = &ms->settings;
1478 DEFUN(cfg_cw, cfg_ms_cw_cmd, "call-waiting",
1479 "Allow waiting calls")
1481 struct osmocom_ms *ms = vty->index;
1482 struct gsm_settings *set = &ms->settings;
1489 DEFUN(cfg_no_auto_answer, cfg_ms_no_auto_answer_cmd, "no auto-answer",
1490 NO_STR "Disable auto-answering calls")
1492 struct osmocom_ms *ms = vty->index;
1493 struct gsm_settings *set = &ms->settings;
1495 set->auto_answer = 0;
1500 DEFUN(cfg_auto_answer, cfg_ms_auto_answer_cmd, "auto-answer",
1501 "Enable auto-answering calls")
1503 struct osmocom_ms *ms = vty->index;
1504 struct gsm_settings *set = &ms->settings;
1506 set->auto_answer = 1;
1511 DEFUN(cfg_clip, cfg_ms_clip_cmd, "clip",
1512 "Force caller ID presentation")
1514 struct osmocom_ms *ms = vty->index;
1515 struct gsm_settings *set = &ms->settings;
1523 DEFUN(cfg_clir, cfg_ms_clir_cmd, "clir",
1524 "Force caller ID restriction")
1526 struct osmocom_ms *ms = vty->index;
1527 struct gsm_settings *set = &ms->settings;
1535 DEFUN(cfg_no_clip, cfg_ms_no_clip_cmd, "no clip",
1536 NO_STR "Disable forcing of caller ID presentation")
1538 struct osmocom_ms *ms = vty->index;
1539 struct gsm_settings *set = &ms->settings;
1546 DEFUN(cfg_no_clir, cfg_ms_no_clir_cmd, "no clir",
1547 NO_STR "Disable forcing of caller ID restriction")
1549 struct osmocom_ms *ms = vty->index;
1550 struct gsm_settings *set = &ms->settings;
1557 DEFUN(cfg_ms_tx_power, cfg_ms_tx_power_cmd, "tx-power (auto|full)",
1558 "Set the way to choose transmit power\nControlled by BTS\n"
1559 "Always full power\nFixed GSM power value if supported")
1561 struct osmocom_ms *ms = vty->index;
1562 struct gsm_settings *set = &ms->settings;
1564 switch (argv[0][0]) {
1566 set->alter_tx_power = 0;
1569 set->alter_tx_power = 1;
1570 set->alter_tx_power_value = 0;
1577 DEFUN(cfg_ms_tx_power_val, cfg_ms_tx_power_val_cmd, "tx-power <0-31>",
1578 "Set the way to choose transmit power\n"
1579 "Fixed GSM power value if supported")
1581 struct osmocom_ms *ms = vty->index;
1582 struct gsm_settings *set = &ms->settings;
1584 set->alter_tx_power = 1;
1585 set->alter_tx_power_value = atoi(argv[0]);
1590 DEFUN(cfg_ms_sim_delay, cfg_ms_sim_delay_cmd, "simulated-delay <-128-127>",
1591 "Simulate a lower or higher distance from the BTS\n"
1592 "Delay in half bits (distance in 553.85 meter steps)")
1594 struct osmocom_ms *ms = vty->index;
1595 struct gsm_settings *set = &ms->settings;
1597 set->alter_delay = atoi(argv[0]);
1598 gsm48_rr_alter_delay(ms);
1603 DEFUN(cfg_ms_no_sim_delay, cfg_ms_no_sim_delay_cmd, "no simulated-delay",
1604 NO_STR "Do not simulate a lower or higher distance from the BTS")
1606 struct osmocom_ms *ms = vty->index;
1607 struct gsm_settings *set = &ms->settings;
1609 set->alter_delay = 0;
1610 gsm48_rr_alter_delay(ms);
1615 DEFUN(cfg_ms_stick, cfg_ms_stick_cmd, "stick <0-1023> [pcs]",
1616 "Stick to the given cell\nARFCN of the cell to stick to\n"
1617 "Given frequency is PCS band (1900) rather than DCS band.")
1619 struct osmocom_ms *ms = vty->index;
1620 struct gsm_settings *set = &ms->settings;
1621 uint16_t arfcn = atoi(argv[0]);
1624 if (arfcn < 512 || arfcn > 810) {
1625 vty_out(vty, "Given ARFCN not in PCS band%s",
1632 set->stick_arfcn = arfcn;
1637 DEFUN(cfg_ms_no_stick, cfg_ms_no_stick_cmd, "no stick",
1638 NO_STR "Do not stick to any cell")
1640 struct osmocom_ms *ms = vty->index;
1641 struct gsm_settings *set = &ms->settings;
1648 DEFUN(cfg_ms_lupd, cfg_ms_lupd_cmd, "location-updating",
1649 "Allow location updating")
1651 struct osmocom_ms *ms = vty->index;
1652 struct gsm_settings *set = &ms->settings;
1659 DEFUN(cfg_ms_no_lupd, cfg_ms_no_lupd_cmd, "no location-updating",
1660 NO_STR "Do not allow location updating")
1662 struct osmocom_ms *ms = vty->index;
1663 struct gsm_settings *set = &ms->settings;
1670 DEFUN(cfg_codec_full, cfg_ms_codec_full_cmd, "codec full-speed",
1671 "Enable codec\nFull speed speech codec")
1673 struct osmocom_ms *ms = vty->index;
1674 struct gsm_settings *set = &ms->settings;
1676 if (!set->full_v1 && !set->full_v2 && !set->full_v3) {
1677 vty_out(vty, "Full-rate codec not supported%s", VTY_NEWLINE);
1684 DEFUN(cfg_codec_full_pref, cfg_ms_codec_full_pref_cmd, "codec full-speed "
1686 "Enable codec\nFull speed speech codec\nPrefer this codec")
1688 struct osmocom_ms *ms = vty->index;
1689 struct gsm_settings *set = &ms->settings;
1691 if (!set->full_v1 && !set->full_v2 && !set->full_v3) {
1692 vty_out(vty, "Full-rate codec not supported%s", VTY_NEWLINE);
1696 set->half_prefer = 0;
1701 DEFUN(cfg_codec_half, cfg_ms_codec_half_cmd, "codec half-speed",
1702 "Enable codec\nHalf speed speech codec")
1704 struct osmocom_ms *ms = vty->index;
1705 struct gsm_settings *set = &ms->settings;
1707 if (!set->half_v1 && !set->half_v3) {
1708 vty_out(vty, "Half-rate codec not supported%s", VTY_NEWLINE);
1717 DEFUN(cfg_codec_half_pref, cfg_ms_codec_half_pref_cmd, "codec half-speed "
1719 "Enable codec\nHalf speed speech codec\nPrefer this codec")
1721 struct osmocom_ms *ms = vty->index;
1722 struct gsm_settings *set = &ms->settings;
1724 if (!set->half_v1 && !set->half_v3) {
1725 vty_out(vty, "Half-rate codec not supported%s", VTY_NEWLINE);
1730 set->half_prefer = 1;
1735 DEFUN(cfg_no_codec_half, cfg_ms_no_codec_half_cmd, "no codec half-speed",
1736 NO_STR "Disable codec\nHalf speed speech codec")
1738 struct osmocom_ms *ms = vty->index;
1739 struct gsm_settings *set = &ms->settings;
1741 if (!set->half_v1 && !set->half_v3) {
1742 vty_out(vty, "Half-rate codec not supported%s", VTY_NEWLINE);
1747 set->half_prefer = 0;
1752 DEFUN(cfg_abbrev, cfg_ms_abbrev_cmd, "abbrev ABBREVIATION NUMBER [NAME]",
1753 "Store given abbreviation number\n1-3 digits abbreviation\n"
1754 "Number to store for the abbreviation "
1755 "(Use digits '0123456789*#abc', and '+' to dial international)\n"
1756 "Name of the abbreviation")
1758 struct osmocom_ms *ms = vty->index;
1759 struct gsm_settings *set = &ms->settings;
1760 struct gsm_settings_abbrev *abbrev;
1763 llist_for_each_entry(abbrev, &set->abbrev, list) {
1764 if (!strcmp(argv[0], abbrev->abbrev)) {
1765 vty_out(vty, "Given abbreviation '%s' already stored, "
1766 "delete first!%s", argv[0], VTY_NEWLINE);
1771 if (strlen(argv[0]) >= sizeof(abbrev->abbrev)) {
1772 vty_out(vty, "Given abbreviation too long%s", VTY_NEWLINE);
1776 for (i = 0; i < strlen(argv[0]); i++) {
1777 if (argv[0][i] < '0' || argv[0][i] > '9') {
1778 vty_out(vty, "Given abbreviation must have digits "
1779 "0..9 only!%s", VTY_NEWLINE);
1784 if (vty_check_number(vty, argv[1]))
1787 abbrev = talloc_zero(l23_ctx, struct gsm_settings_abbrev);
1789 vty_out(vty, "No Memory!%s", VTY_NEWLINE);
1792 llist_add_tail(&abbrev->list, &set->abbrev);
1793 strncpy(abbrev->abbrev, argv[0], sizeof(abbrev->abbrev) - 1);
1794 strncpy(abbrev->number, argv[1], sizeof(abbrev->number) - 1);
1796 strncpy(abbrev->name, argv[2], sizeof(abbrev->name) - 1);
1801 DEFUN(cfg_no_abbrev, cfg_ms_no_abbrev_cmd, "no abbrev [ABBREVIATION]",
1802 NO_STR "Remove given abbreviation number or all numbers\n"
1803 "Abbreviation number to remove")
1805 struct osmocom_ms *ms = vty->index;
1806 struct gsm_settings *set = &ms->settings;
1807 struct gsm_settings_abbrev *abbrev, *abbrev2;
1808 uint8_t deleted = 0;
1810 llist_for_each_entry_safe(abbrev, abbrev2, &set->abbrev, list) {
1811 if (argc < 1 || !strcmp(argv[0], abbrev->abbrev)) {
1812 llist_del(&abbrev->list);
1817 if (argc >= 1 && !deleted) {
1818 vty_out(vty, "Given abbreviation '%s' not found!%s",
1819 argv[0], VTY_NEWLINE);
1826 static int config_write_dummy(struct vty *vty)
1831 /* per support config */
1832 DEFUN(cfg_ms_support, cfg_ms_support_cmd, "support",
1833 "Define supported features")
1835 vty->node = SUPPORT_NODE;
1840 #define SUP_EN(cfg, cfg_cmd, item, cmd, desc, restart) \
1841 DEFUN(cfg, cfg_cmd, cmd, "Enable " desc "support") \
1843 struct osmocom_ms *ms = vty->index; \
1844 struct gsm_settings *set = &ms->settings; \
1845 struct gsm_support *sup = &ms->support; \
1847 vty_out(vty, desc " not supported%s", VTY_NEWLINE); \
1849 return CMD_SUCCESS; \
1850 return CMD_WARNING; \
1853 vty_restart(vty, ms); \
1855 return CMD_SUCCESS; \
1858 #define SUP_DI(cfg, cfg_cmd, item, cmd, desc, restart) \
1859 DEFUN(cfg, cfg_cmd, "no " cmd, NO_STR "Disable " desc " support") \
1861 struct osmocom_ms *ms = vty->index; \
1862 struct gsm_settings *set = &ms->settings; \
1863 struct gsm_support *sup = &ms->support; \
1865 vty_out(vty, desc " not supported%s", VTY_NEWLINE); \
1867 return CMD_SUCCESS; \
1868 return CMD_WARNING; \
1871 vty_restart(vty, ms); \
1873 return CMD_SUCCESS; \
1876 #define SET_EN(cfg, cfg_cmd, item, cmd, desc, restart) \
1877 DEFUN(cfg, cfg_cmd, cmd, "Enable " desc "support") \
1879 struct osmocom_ms *ms = vty->index; \
1880 struct gsm_settings *set = &ms->settings; \
1882 vty_restart(vty, ms); \
1884 return CMD_SUCCESS; \
1887 #define SET_DI(cfg, cfg_cmd, item, cmd, desc, restart) \
1888 DEFUN(cfg, cfg_cmd, "no " cmd, NO_STR "Disable " desc " support") \
1890 struct osmocom_ms *ms = vty->index; \
1891 struct gsm_settings *set = &ms->settings; \
1893 vty_restart(vty, ms); \
1895 return CMD_SUCCESS; \
1898 SET_EN(cfg_ms_sup_dtmf, cfg_ms_sup_dtmf_cmd, cc_dtmf, "dtmf", "DTMF", 0);
1899 SET_DI(cfg_ms_sup_no_dtmf, cfg_ms_sup_no_dtmf_cmd, cc_dtmf, "dtmf", "DTMF", 0);
1900 SUP_EN(cfg_ms_sup_sms, cfg_ms_sup_sms_cmd, sms_ptp, "sms", "SMS", 0);
1901 SUP_DI(cfg_ms_sup_no_sms, cfg_ms_sup_no_sms_cmd, sms_ptp, "sms", "SMS", 0);
1902 SUP_EN(cfg_ms_sup_a5_1, cfg_ms_sup_a5_1_cmd, a5_1, "a5/1", "A5/1", 0);
1903 SUP_DI(cfg_ms_sup_no_a5_1, cfg_ms_sup_no_a5_1_cmd, a5_1, "a5/1", "A5/1", 0);
1904 SUP_EN(cfg_ms_sup_a5_2, cfg_ms_sup_a5_2_cmd, a5_2, "a5/2", "A5/2", 0);
1905 SUP_DI(cfg_ms_sup_no_a5_2, cfg_ms_sup_no_a5_2_cmd, a5_2, "a5/2", "A5/2", 0);
1906 SUP_EN(cfg_ms_sup_a5_3, cfg_ms_sup_a5_3_cmd, a5_3, "a5/3", "A5/3", 0);
1907 SUP_DI(cfg_ms_sup_no_a5_3, cfg_ms_sup_no_a5_3_cmd, a5_3, "a5/3", "A5/3", 0);
1908 SUP_EN(cfg_ms_sup_a5_4, cfg_ms_sup_a5_4_cmd, a5_4, "a5/4", "A5/4", 0);
1909 SUP_DI(cfg_ms_sup_no_a5_4, cfg_ms_sup_no_a5_4_cmd, a5_4, "a5/4", "A5/4", 0);
1910 SUP_EN(cfg_ms_sup_a5_5, cfg_ms_sup_a5_5_cmd, a5_5, "a5/5", "A5/5", 0);
1911 SUP_DI(cfg_ms_sup_no_a5_5, cfg_ms_sup_no_a5_5_cmd, a5_5, "a5/5", "A5/5", 0);
1912 SUP_EN(cfg_ms_sup_a5_6, cfg_ms_sup_a5_6_cmd, a5_6, "a5/6", "A5/6", 0);
1913 SUP_DI(cfg_ms_sup_no_a5_6, cfg_ms_sup_no_a5_6_cmd, a5_6, "a5/6", "A5/6", 0);
1914 SUP_EN(cfg_ms_sup_a5_7, cfg_ms_sup_a5_7_cmd, a5_7, "a5/7", "A5/7", 0);
1915 SUP_DI(cfg_ms_sup_no_a5_7, cfg_ms_sup_no_a5_7_cmd, a5_7, "a5/7", "A5/7", 1);
1916 SUP_EN(cfg_ms_sup_p_gsm, cfg_ms_sup_p_gsm_cmd, p_gsm, "p-gsm", "P-GSM (900)",
1918 SUP_DI(cfg_ms_sup_no_p_gsm, cfg_ms_sup_no_p_gsm_cmd, p_gsm, "p-gsm",
1920 SUP_EN(cfg_ms_sup_e_gsm, cfg_ms_sup_e_gsm_cmd, e_gsm, "e-gsm", "E-GSM (850)",
1922 SUP_DI(cfg_ms_sup_no_e_gsm, cfg_ms_sup_no_e_gsm_cmd, e_gsm, "e-gsm",
1924 SUP_EN(cfg_ms_sup_r_gsm, cfg_ms_sup_r_gsm_cmd, r_gsm, "r-gsm", "R-GSM (850)",
1926 SUP_DI(cfg_ms_sup_no_r_gsm, cfg_ms_sup_no_r_gsm_cmd, r_gsm, "r-gsm",
1928 SUP_EN(cfg_ms_sup_dcs, cfg_ms_sup_dcs_cmd, dcs, "dcs", "DCS (1800)", 0);
1929 SUP_DI(cfg_ms_sup_no_dcs, cfg_ms_sup_no_dcs_cmd, dcs, "dcs", "DCS (1800)", 0);
1930 SUP_EN(cfg_ms_sup_gsm_850, cfg_ms_sup_gsm_850_cmd, gsm_850, "gsm-850",
1932 SUP_DI(cfg_ms_sup_no_gsm_850, cfg_ms_sup_no_gsm_850_cmd, gsm_850, "gsm-850",
1934 SUP_EN(cfg_ms_sup_pcs, cfg_ms_sup_pcs_cmd, pcs, "pcs", "PCS (1900)", 0);
1935 SUP_DI(cfg_ms_sup_no_pcs, cfg_ms_sup_no_pcs_cmd, pcs, "pcs", "PCS (1900)", 0);
1936 SUP_EN(cfg_ms_sup_gsm_480, cfg_ms_sup_gsm_480_cmd, gsm_480, "gsm-480",
1938 SUP_DI(cfg_ms_sup_no_gsm_480, cfg_ms_sup_no_gsm_480_cmd, gsm_480, "gsm-480",
1940 SUP_EN(cfg_ms_sup_gsm_450, cfg_ms_sup_gsm_450_cmd, gsm_450, "gsm-450",
1942 SUP_DI(cfg_ms_sup_no_gsm_450, cfg_ms_sup_no_gsm_450_cmd, gsm_450, "gsm-450",
1945 DEFUN(cfg_ms_sup_class_900, cfg_ms_sup_class_900_cmd, "class-900 (1|2|3|4|5)",
1946 "Select power class for GSM 900\n"
1953 struct osmocom_ms *ms = vty->index;
1954 struct gsm_settings *set = &ms->settings;
1955 struct gsm_support *sup = &ms->support;
1957 set->class_900 = atoi(argv[0]);
1959 if (set->class_900 < sup->class_900 && !vty_reading)
1960 vty_out(vty, "Note: You selected a higher class than supported "
1961 " by hardware!%s", VTY_NEWLINE);
1966 DEFUN(cfg_ms_sup_class_850, cfg_ms_sup_class_850_cmd, "class-850 (1|2|3|4|5)",
1967 "Select power class for GSM 850\n"
1974 struct osmocom_ms *ms = vty->index;
1975 struct gsm_settings *set = &ms->settings;
1976 struct gsm_support *sup = &ms->support;
1978 set->class_850 = atoi(argv[0]);
1980 if (set->class_850 < sup->class_850 && !vty_reading)
1981 vty_out(vty, "Note: You selected a higher class than supported "
1982 " by hardware!%s", VTY_NEWLINE);
1987 DEFUN(cfg_ms_sup_class_400, cfg_ms_sup_class_400_cmd, "class-400 (1|2|3|4|5)",
1988 "Select power class for GSM 400 (480 and 450)\n"
1995 struct osmocom_ms *ms = vty->index;
1996 struct gsm_settings *set = &ms->settings;
1997 struct gsm_support *sup = &ms->support;
1999 set->class_400 = atoi(argv[0]);
2001 if (set->class_400 < sup->class_400 && !vty_reading)
2002 vty_out(vty, "Note: You selected a higher class than supported "
2003 " by hardware!%s", VTY_NEWLINE);
2008 DEFUN(cfg_ms_sup_class_dcs, cfg_ms_sup_class_dcs_cmd, "class-dcs (1|2|3)",
2009 "Select power class for DCS 1800\n"
2014 struct osmocom_ms *ms = vty->index;
2015 struct gsm_settings *set = &ms->settings;
2016 struct gsm_support *sup = &ms->support;
2018 set->class_dcs = atoi(argv[0]);
2020 if (((set->class_dcs + 1) & 3) < ((sup->class_dcs + 1) & 3)
2022 vty_out(vty, "Note: You selected a higher class than supported "
2023 " by hardware!%s", VTY_NEWLINE);
2028 DEFUN(cfg_ms_sup_class_pcs, cfg_ms_sup_class_pcs_cmd, "class-pcs (1|2|3)",
2029 "Select power class for PCS 1900\n"
2034 struct osmocom_ms *ms = vty->index;
2035 struct gsm_settings *set = &ms->settings;
2036 struct gsm_support *sup = &ms->support;
2038 set->class_pcs = atoi(argv[0]);
2040 if (((set->class_pcs + 1) & 3) < ((sup->class_pcs + 1) & 3)
2042 vty_out(vty, "Note: You selected a higher class than supported "
2043 " by hardware!%s", VTY_NEWLINE);
2048 DEFUN(cfg_ms_sup_ch_cap, cfg_ms_sup_ch_cap_cmd, "channel-capability "
2049 "(sdcch|sdcch+tchf|sdcch+tchf+tchh)",
2050 "Select channel capability\nSDCCH only\nSDCCH + TCH/F\nSDCCH + TCH/H")
2052 struct osmocom_ms *ms = vty->index;
2053 struct gsm_settings *set = &ms->settings;
2054 struct gsm_support *sup = &ms->support;
2057 if (!strcmp(argv[0], "sdcch+tchf+tchh"))
2058 ch_cap = GSM_CAP_SDCCH_TCHF_TCHH;
2059 else if (!strcmp(argv[0], "sdcch+tchf"))
2060 ch_cap = GSM_CAP_SDCCH_TCHF;
2062 ch_cap = GSM_CAP_SDCCH;
2064 if (ch_cap > sup->ch_cap && !vty_reading) {
2065 vty_out(vty, "You selected an higher capability than supported "
2066 " by hardware!%s", VTY_NEWLINE);
2070 if (ch_cap != set->ch_cap
2071 && (ch_cap == GSM_CAP_SDCCH || set->ch_cap == GSM_CAP_SDCCH))
2072 vty_restart(vty, ms);
2074 set->ch_cap = ch_cap;
2079 SUP_EN(cfg_ms_sup_full_v1, cfg_ms_sup_full_v1_cmd, full_v1, "full-speech-v1",
2080 "Full rate speech V1", 0);
2081 SUP_DI(cfg_ms_sup_no_full_v1, cfg_ms_sup_no_full_v1_cmd, full_v1,
2082 "full-speech-v1", "Full rate speech V1", 0);
2083 SUP_EN(cfg_ms_sup_full_v2, cfg_ms_sup_full_v2_cmd, full_v2, "full-speech-v2",
2084 "Full rate speech V2 (EFR)", 0);
2085 SUP_DI(cfg_ms_sup_no_full_v2, cfg_ms_sup_no_full_v2_cmd, full_v2,
2086 "full-speech-v2", "Full rate speech V2 (EFR)", 0);
2087 SUP_EN(cfg_ms_sup_full_v3, cfg_ms_sup_full_v3_cmd, full_v3, "full-speech-v3",
2088 "Full rate speech V3 (AMR)", 0);
2089 SUP_DI(cfg_ms_sup_no_full_v3, cfg_ms_sup_no_full_v3_cmd, full_v3,
2090 "full-speech-v3", "Full rate speech V3 (AMR)", 0);
2091 SUP_EN(cfg_ms_sup_half_v1, cfg_ms_sup_half_v1_cmd, half_v1, "half-speech-v1",
2092 "Half rate speech V1", 0);
2093 SUP_DI(cfg_ms_sup_no_half_v1, cfg_ms_sup_no_half_v1_cmd, half_v1,
2094 "half-speech-v1", "Half rate speech V1", 0);
2095 SUP_EN(cfg_ms_sup_half_v3, cfg_ms_sup_half_v3_cmd, half_v3, "half-speech-v3",
2096 "Half rate speech V3 (AMR)", 0);
2097 SUP_DI(cfg_ms_sup_no_half_v3, cfg_ms_sup_no_half_v3_cmd, half_v3,
2098 "half-speech-v3", "Half rate speech V3 (AMR)", 0);
2100 DEFUN(cfg_ms_sup_min_rxlev, cfg_ms_sup_min_rxlev_cmd, "min-rxlev <-110--47>",
2101 "Set the minimum receive level to select a cell\n"
2102 "Minimum receive level from -110 dBm to -47 dBm")
2104 struct osmocom_ms *ms = vty->index;
2105 struct gsm_settings *set = &ms->settings;
2107 set->min_rxlev_db = atoi(argv[0]);
2112 DEFUN(cfg_ms_sup_dsc_max, cfg_ms_sup_dsc_max_cmd, "dsc-max <90-500>",
2113 "Set the maximum DSC value. Standard is 90. Increase to make mobile "
2114 "more reliable against bad RX signal. This increase the propability "
2115 "of missing a paging requests\n"
2116 "DSC initial and maximum value (standard is 90)")
2118 struct osmocom_ms *ms = vty->index;
2119 struct gsm_settings *set = &ms->settings;
2121 set->dsc_max = atoi(argv[0]);
2126 /* per testsim config */
2127 DEFUN(cfg_ms_testsim, cfg_ms_testsim_cmd, "test-sim",
2128 "Configure test SIM emulation")
2130 vty->node = TESTSIM_NODE;
2135 DEFUN(cfg_test_imsi, cfg_test_imsi_cmd, "imsi IMSI",
2136 "Set IMSI on test card\n15 digits IMSI")
2138 struct osmocom_ms *ms = vty->index;
2139 struct gsm_settings *set = &ms->settings;
2140 char *error = gsm_check_imsi(argv[0]);
2143 vty_out(vty, "%s%s", error, VTY_NEWLINE);
2147 strcpy(set->test_imsi, argv[0]);
2149 vty_restart(vty, ms);
2153 #define HEX_STR "\nByte as two digits hexadecimal"
2154 DEFUN(cfg_test_ki_xor, cfg_test_ki_xor_cmd, "ki xor HEX HEX HEX HEX HEX HEX "
2155 "HEX HEX HEX HEX HEX HEX",
2156 "Set Key (Kc) on test card\nUse XOR algorithm" HEX_STR HEX_STR HEX_STR
2157 HEX_STR HEX_STR HEX_STR HEX_STR HEX_STR HEX_STR HEX_STR HEX_STR HEX_STR)
2159 struct osmocom_ms *ms = vty->index;
2160 struct gsm_settings *set = &ms->settings;
2165 for (i = 0; i < 12; i++) {
2167 if (!strncmp(p, "0x", 2))
2169 if (strlen(p) != 2) {
2170 vty_out(vty, "Expecting two digits hex value (with or "
2171 "without 0x in front)%s", VTY_NEWLINE);
2174 ki[i] = strtoul(p, NULL, 16);
2177 set->test_ki_type = GSM_SIM_KEY_XOR;
2178 memcpy(set->test_ki, ki, 12);
2182 DEFUN(cfg_test_ki_comp128, cfg_test_ki_comp128_cmd, "ki comp128 HEX HEX HEX "
2183 "HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX",
2184 "Set Key (Kc) on test card\nUse XOR algorithm" HEX_STR HEX_STR HEX_STR
2185 HEX_STR HEX_STR HEX_STR HEX_STR HEX_STR HEX_STR HEX_STR HEX_STR HEX_STR
2186 HEX_STR HEX_STR HEX_STR HEX_STR)
2188 struct osmocom_ms *ms = vty->index;
2189 struct gsm_settings *set = &ms->settings;
2194 for (i = 0; i < 16; i++) {
2196 if (!strncmp(p, "0x", 2))
2198 if (strlen(p) != 2) {
2199 vty_out(vty, "Expecting two digits hex value (with or "
2200 "without 0x in front)%s", VTY_NEWLINE);
2203 ki[i] = strtoul(p, NULL, 16);
2206 set->test_ki_type = GSM_SIM_KEY_COMP128;
2207 memcpy(set->test_ki, ki, 16);
2211 DEFUN(cfg_test_barr, cfg_test_barr_cmd, "barred-access",
2212 "Allow access to barred cells")
2214 struct osmocom_ms *ms = vty->index;
2215 struct gsm_settings *set = &ms->settings;
2222 DEFUN(cfg_test_no_barr, cfg_test_no_barr_cmd, "no barred-access",
2223 NO_STR "Deny access to barred cells")
2225 struct osmocom_ms *ms = vty->index;
2226 struct gsm_settings *set = &ms->settings;
2233 DEFUN(cfg_test_no_rplmn, cfg_test_no_rplmn_cmd, "no rplmn",
2234 NO_STR "Unset Registered PLMN")
2236 struct osmocom_ms *ms = vty->index;
2237 struct gsm_settings *set = &ms->settings;
2239 set->test_rplmn_valid = 0;
2241 vty_restart(vty, ms);
2245 DEFUN(cfg_test_rplmn, cfg_test_rplmn_cmd, "rplmn MCC MNC [LAC] [TMSI]",
2246 "Set Registered PLMN\nMobile Country Code\nMobile Network Code\n"
2247 "Optionally set locatio area code\n"
2248 "Optionally set current assigned TMSI")
2250 struct osmocom_ms *ms = vty->index;
2251 struct gsm_settings *set = &ms->settings;
2252 uint16_t mcc = gsm_input_mcc((char *)argv[0]),
2253 mnc = gsm_input_mnc((char *)argv[1]);
2256 vty_out(vty, "Given MCC invalid%s", VTY_NEWLINE);
2260 vty_out(vty, "Given MNC invalid%s", VTY_NEWLINE);
2263 set->test_rplmn_valid = 1;
2264 set->test_rplmn_mcc = mcc;
2265 set->test_rplmn_mnc = mnc;
2268 set->test_lac = strtoul(argv[2], NULL, 16);
2270 set->test_lac = 0xfffe;
2273 set->test_tmsi = strtoul(argv[3], NULL, 16);
2275 set->test_tmsi = 0xffffffff;
2277 vty_restart(vty, ms);
2281 DEFUN(cfg_test_hplmn, cfg_test_hplmn_cmd, "hplmn-search (everywhere|foreign-country)",
2282 "Set Home PLMN search mode\n"
2283 "Search for HPLMN when on any other network\n"
2284 "Search for HPLMN when in a different country")
2286 struct osmocom_ms *ms = vty->index;
2287 struct gsm_settings *set = &ms->settings;
2289 switch (argv[0][0]) {
2291 set->test_always = 1;
2294 set->test_always = 0;
2298 vty_restart(vty, ms);
2302 DEFUN(cfg_no_shutdown, cfg_ms_no_shutdown_cmd, "no shutdown",
2303 NO_STR "Activate and run MS")
2305 struct osmocom_ms *ms = vty->index, *tmp;
2308 if (ms->shutdown != 2)
2311 llist_for_each_entry(tmp, &ms_list, entity) {
2312 if (tmp->shutdown == 2)
2314 if (!strcmp(ms->settings.layer2_socket_path,
2315 tmp->settings.layer2_socket_path)) {
2316 vty_out(vty, "Cannot start MS '%s', because MS '%s' "
2317 "use the same layer2-socket.%sPlease shutdown "
2318 "MS '%s' first.%s", ms->name, tmp->name,
2319 VTY_NEWLINE, tmp->name, VTY_NEWLINE);
2322 if (!strcmp(ms->settings.sap_socket_path,
2323 tmp->settings.sap_socket_path)) {
2324 vty_out(vty, "Cannot start MS '%s', because MS '%s' "
2325 "use the same sap-socket.%sPlease shutdown "
2326 "MS '%s' first.%s", ms->name, tmp->name,
2327 VTY_NEWLINE, tmp->name, VTY_NEWLINE);
2332 rc = mobile_init(ms);
2334 vty_out(vty, "Connection to layer 1 failed!%s",
2342 DEFUN(cfg_shutdown, cfg_ms_shutdown_cmd, "shutdown",
2343 "Shut down and deactivate MS")
2345 struct osmocom_ms *ms = vty->index;
2347 if (ms->shutdown == 0)
2353 DEFUN(cfg_shutdown_force, cfg_ms_shutdown_force_cmd, "shutdown force",
2354 "Shut down and deactivate MS\nDo not perform IMSI detach")
2356 struct osmocom_ms *ms = vty->index;
2358 if (ms->shutdown <= 1)
2364 enum node_type ms_vty_go_parent(struct vty *vty)
2366 switch (vty->node) {
2368 vty->node = CONFIG_NODE;
2373 vty->node = MS_NODE;
2376 vty->node = CONFIG_NODE;
2382 /* Down vty node level. */
2383 gDEFUN(ournode_exit,
2384 ournode_exit_cmd, "exit", "Exit current mode and down to previous mode\n")
2386 switch (vty->node) {
2388 vty->node = CONFIG_NODE;
2393 vty->node = MS_NODE;
2401 /* End of configuration. */
2403 ournode_end_cmd, "end", "End current mode and change to enable mode.")
2405 switch (vty->node) {
2408 /* Nothing to do. */
2415 vty_config_unlock(vty);
2416 vty->node = ENABLE_NODE;
2418 vty->index_sub = NULL;
2426 DEFUN(off, off_cmd, "off",
2427 "Turn mobiles off (shutdown) and exit")
2429 osmo_signal_dispatch(SS_GLOBAL, S_GLOBAL_SHUTDOWN, NULL);
2434 #define SUP_NODE(item) \
2435 install_element(SUPPORT_NODE, &cfg_ms_sup_item_cmd);
2437 int ms_vty_init(void)
2439 install_element_ve(&show_ms_cmd);
2440 install_element_ve(&show_subscr_cmd);
2441 install_element_ve(&show_support_cmd);
2442 install_element_ve(&show_cell_cmd);
2443 install_element_ve(&show_cell_si_cmd);
2444 install_element_ve(&show_ba_cmd);
2445 install_element_ve(&show_forb_la_cmd);
2446 install_element_ve(&show_forb_plmn_cmd);
2447 install_element_ve(&monitor_network_cmd);
2448 install_element_ve(&no_monitor_network_cmd);
2449 install_element(ENABLE_NODE, &off_cmd);
2451 install_element(ENABLE_NODE, &sim_test_cmd);
2452 install_element(ENABLE_NODE, &sim_reader_cmd);
2453 install_element(ENABLE_NODE, &sim_remove_cmd);
2454 install_element(ENABLE_NODE, &sim_pin_cmd);
2455 install_element(ENABLE_NODE, &sim_disable_pin_cmd);
2456 install_element(ENABLE_NODE, &sim_enable_pin_cmd);
2457 install_element(ENABLE_NODE, &sim_change_pin_cmd);
2458 install_element(ENABLE_NODE, &sim_unblock_pin_cmd);
2459 install_element(ENABLE_NODE, &sim_lai_cmd);
2460 install_element(ENABLE_NODE, &network_search_cmd);
2461 install_element(ENABLE_NODE, &network_show_cmd);
2462 install_element(ENABLE_NODE, &network_select_cmd);
2463 install_element(ENABLE_NODE, &call_cmd);
2464 install_element(ENABLE_NODE, &call_retr_cmd);
2465 install_element(ENABLE_NODE, &call_dtmf_cmd);
2468 install_element(CONFIG_NODE, &cfg_gps_host_cmd);
2470 install_element(CONFIG_NODE, &cfg_gps_device_cmd);
2471 install_element(CONFIG_NODE, &cfg_gps_baud_cmd);
2472 install_element(CONFIG_NODE, &cfg_gps_enable_cmd);
2473 install_element(CONFIG_NODE, &cfg_no_gps_enable_cmd);
2475 install_element(CONFIG_NODE, &cfg_hide_default_cmd);
2476 install_element(CONFIG_NODE, &cfg_no_hide_default_cmd);
2478 install_element(CONFIG_NODE, &cfg_ms_cmd);
2479 install_element(CONFIG_NODE, &cfg_ms_create_cmd);
2480 install_element(CONFIG_NODE, &cfg_ms_rename_cmd);
2481 install_element(CONFIG_NODE, &cfg_no_ms_cmd);
2482 install_element(CONFIG_NODE, &ournode_end_cmd);
2483 install_node(&ms_node, config_write);
2484 install_default(MS_NODE);
2485 install_element(MS_NODE, &ournode_exit_cmd);
2486 install_element(MS_NODE, &ournode_end_cmd);
2487 install_element(MS_NODE, &cfg_ms_show_this_cmd);
2488 install_element(MS_NODE, &cfg_ms_layer2_cmd);
2489 install_element(MS_NODE, &cfg_ms_sap_cmd);
2490 install_element(MS_NODE, &cfg_ms_sim_cmd);
2491 install_element(MS_NODE, &cfg_ms_mode_cmd);
2492 install_element(MS_NODE, &cfg_ms_imei_cmd);
2493 install_element(MS_NODE, &cfg_ms_imei_fixed_cmd);
2494 install_element(MS_NODE, &cfg_ms_imei_random_cmd);
2495 install_element(MS_NODE, &cfg_ms_no_emerg_imsi_cmd);
2496 install_element(MS_NODE, &cfg_ms_emerg_imsi_cmd);
2497 install_element(MS_NODE, &cfg_ms_cw_cmd);
2498 install_element(MS_NODE, &cfg_ms_no_cw_cmd);
2499 install_element(MS_NODE, &cfg_ms_auto_answer_cmd);
2500 install_element(MS_NODE, &cfg_ms_no_auto_answer_cmd);
2501 install_element(MS_NODE, &cfg_ms_clip_cmd);
2502 install_element(MS_NODE, &cfg_ms_clir_cmd);
2503 install_element(MS_NODE, &cfg_ms_no_clip_cmd);
2504 install_element(MS_NODE, &cfg_ms_no_clir_cmd);
2505 install_element(MS_NODE, &cfg_ms_tx_power_cmd);
2506 install_element(MS_NODE, &cfg_ms_tx_power_val_cmd);
2507 install_element(MS_NODE, &cfg_ms_sim_delay_cmd);
2508 install_element(MS_NODE, &cfg_ms_no_sim_delay_cmd);
2509 install_element(MS_NODE, &cfg_ms_stick_cmd);
2510 install_element(MS_NODE, &cfg_ms_no_stick_cmd);
2511 install_element(MS_NODE, &cfg_ms_lupd_cmd);
2512 install_element(MS_NODE, &cfg_ms_no_lupd_cmd);
2513 install_element(MS_NODE, &cfg_ms_codec_full_cmd);
2514 install_element(MS_NODE, &cfg_ms_codec_full_pref_cmd);
2515 install_element(MS_NODE, &cfg_ms_codec_half_cmd);
2516 install_element(MS_NODE, &cfg_ms_codec_half_pref_cmd);
2517 install_element(MS_NODE, &cfg_ms_no_codec_half_cmd);
2518 install_element(MS_NODE, &cfg_ms_abbrev_cmd);
2519 install_element(MS_NODE, &cfg_ms_no_abbrev_cmd);
2520 install_element(MS_NODE, &cfg_ms_testsim_cmd);
2521 install_element(MS_NODE, &cfg_ms_support_cmd);
2522 install_node(&support_node, config_write_dummy);
2523 install_default(SUPPORT_NODE);
2524 install_element(SUPPORT_NODE, &ournode_exit_cmd);
2525 install_element(SUPPORT_NODE, &ournode_end_cmd);
2526 install_element(SUPPORT_NODE, &cfg_ms_sup_dtmf_cmd);
2527 install_element(SUPPORT_NODE, &cfg_ms_sup_no_dtmf_cmd);
2528 install_element(SUPPORT_NODE, &cfg_ms_sup_sms_cmd);
2529 install_element(SUPPORT_NODE, &cfg_ms_sup_no_sms_cmd);
2530 install_element(SUPPORT_NODE, &cfg_ms_sup_a5_1_cmd);
2531 install_element(SUPPORT_NODE, &cfg_ms_sup_no_a5_1_cmd);
2532 install_element(SUPPORT_NODE, &cfg_ms_sup_a5_2_cmd);
2533 install_element(SUPPORT_NODE, &cfg_ms_sup_no_a5_2_cmd);
2534 install_element(SUPPORT_NODE, &cfg_ms_sup_a5_3_cmd);
2535 install_element(SUPPORT_NODE, &cfg_ms_sup_no_a5_3_cmd);
2536 install_element(SUPPORT_NODE, &cfg_ms_sup_a5_4_cmd);
2537 install_element(SUPPORT_NODE, &cfg_ms_sup_no_a5_4_cmd);
2538 install_element(SUPPORT_NODE, &cfg_ms_sup_a5_5_cmd);
2539 install_element(SUPPORT_NODE, &cfg_ms_sup_no_a5_5_cmd);
2540 install_element(SUPPORT_NODE, &cfg_ms_sup_a5_6_cmd);
2541 install_element(SUPPORT_NODE, &cfg_ms_sup_no_a5_6_cmd);
2542 install_element(SUPPORT_NODE, &cfg_ms_sup_a5_7_cmd);
2543 install_element(SUPPORT_NODE, &cfg_ms_sup_no_a5_7_cmd);
2544 install_element(SUPPORT_NODE, &cfg_ms_sup_p_gsm_cmd);
2545 install_element(SUPPORT_NODE, &cfg_ms_sup_no_p_gsm_cmd);
2546 install_element(SUPPORT_NODE, &cfg_ms_sup_e_gsm_cmd);
2547 install_element(SUPPORT_NODE, &cfg_ms_sup_no_e_gsm_cmd);
2548 install_element(SUPPORT_NODE, &cfg_ms_sup_r_gsm_cmd);
2549 install_element(SUPPORT_NODE, &cfg_ms_sup_no_r_gsm_cmd);
2550 install_element(SUPPORT_NODE, &cfg_ms_sup_dcs_cmd);
2551 install_element(SUPPORT_NODE, &cfg_ms_sup_no_dcs_cmd);
2552 install_element(SUPPORT_NODE, &cfg_ms_sup_gsm_850_cmd);
2553 install_element(SUPPORT_NODE, &cfg_ms_sup_no_gsm_850_cmd);
2554 install_element(SUPPORT_NODE, &cfg_ms_sup_pcs_cmd);
2555 install_element(SUPPORT_NODE, &cfg_ms_sup_no_pcs_cmd);
2556 install_element(SUPPORT_NODE, &cfg_ms_sup_gsm_480_cmd);
2557 install_element(SUPPORT_NODE, &cfg_ms_sup_no_gsm_480_cmd);
2558 install_element(SUPPORT_NODE, &cfg_ms_sup_gsm_450_cmd);
2559 install_element(SUPPORT_NODE, &cfg_ms_sup_no_gsm_450_cmd);
2560 install_element(SUPPORT_NODE, &cfg_ms_sup_class_900_cmd);
2561 install_element(SUPPORT_NODE, &cfg_ms_sup_class_dcs_cmd);
2562 install_element(SUPPORT_NODE, &cfg_ms_sup_class_850_cmd);
2563 install_element(SUPPORT_NODE, &cfg_ms_sup_class_pcs_cmd);
2564 install_element(SUPPORT_NODE, &cfg_ms_sup_class_400_cmd);
2565 install_element(SUPPORT_NODE, &cfg_ms_sup_ch_cap_cmd);
2566 install_element(SUPPORT_NODE, &cfg_ms_sup_full_v1_cmd);
2567 install_element(SUPPORT_NODE, &cfg_ms_sup_no_full_v1_cmd);
2568 install_element(SUPPORT_NODE, &cfg_ms_sup_full_v2_cmd);
2569 install_element(SUPPORT_NODE, &cfg_ms_sup_no_full_v2_cmd);
2570 install_element(SUPPORT_NODE, &cfg_ms_sup_full_v3_cmd);
2571 install_element(SUPPORT_NODE, &cfg_ms_sup_no_full_v3_cmd);
2572 install_element(SUPPORT_NODE, &cfg_ms_sup_half_v1_cmd);
2573 install_element(SUPPORT_NODE, &cfg_ms_sup_no_half_v1_cmd);
2574 install_element(SUPPORT_NODE, &cfg_ms_sup_half_v3_cmd);
2575 install_element(SUPPORT_NODE, &cfg_ms_sup_no_half_v3_cmd);
2576 install_element(SUPPORT_NODE, &cfg_ms_sup_min_rxlev_cmd);
2577 install_element(SUPPORT_NODE, &cfg_ms_sup_dsc_max_cmd);
2578 install_node(&testsim_node, config_write_dummy);
2579 install_default(TESTSIM_NODE);
2580 install_element(TESTSIM_NODE, &ournode_exit_cmd);
2581 install_element(TESTSIM_NODE, &ournode_end_cmd);
2582 install_element(TESTSIM_NODE, &cfg_test_imsi_cmd);
2583 install_element(TESTSIM_NODE, &cfg_test_ki_xor_cmd);
2584 install_element(TESTSIM_NODE, &cfg_test_ki_comp128_cmd);
2585 install_element(TESTSIM_NODE, &cfg_test_barr_cmd);
2586 install_element(TESTSIM_NODE, &cfg_test_no_barr_cmd);
2587 install_element(TESTSIM_NODE, &cfg_test_no_rplmn_cmd);
2588 install_element(TESTSIM_NODE, &cfg_test_rplmn_cmd);
2589 install_element(TESTSIM_NODE, &cfg_test_hplmn_cmd);
2590 install_element(MS_NODE, &cfg_ms_shutdown_cmd);
2591 install_element(MS_NODE, &cfg_ms_shutdown_force_cmd);
2592 install_element(MS_NODE, &cfg_ms_no_shutdown_cmd);
2597 void vty_notify(struct osmocom_ms *ms, const char *fmt, ...)
2599 struct telnet_connection *connection;
2605 va_start(args, fmt);
2606 vsnprintf(buffer, sizeof(buffer) - 1, fmt, args);
2607 buffer[sizeof(buffer) - 1] = '\0';
2614 llist_for_each_entry(connection, &active_connections, entry) {
2615 vty = connection->vty;
2619 vty_out(vty, "%s%% (MS %s)%s", VTY_NEWLINE, ms->name,
2623 if (buffer[strlen(buffer) - 1] == '\n') {
2624 buffer[strlen(buffer) - 1] = '\0';
2625 vty_out(vty, "%% %s%s", buffer, VTY_NEWLINE);
2626 buffer[strlen(buffer)] = '\n';
2628 vty_out(vty, "%% %s", buffer);