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 <vty/command.h>
29 #include <vty/buffer.h>
32 #include <osmocom/osmocom_data.h>
33 #include <osmocom/networks.h>
35 int mncc_call(struct osmocom_ms *ms, char *number);
36 int mncc_hangup(struct osmocom_ms *ms);
37 int mncc_answer(struct osmocom_ms *ms);
39 extern struct llist_head ms_list;
41 struct cmd_node ms_node = {
47 struct cmd_node testsim_node = {
53 static void print_vty(void *priv, const char *fmt, ...)
56 struct vty *vty = priv;
60 vsnprintf(buffer, sizeof(buffer) - 1, fmt, args);
61 buffer[sizeof(buffer) - 1] = '\0';
65 if (buffer[strlen(buffer) - 1] == '\n') {
66 buffer[strlen(buffer) - 1] = '\0';
67 vty_out(vty, "%s%s", buffer, VTY_NEWLINE);
69 vty_out(vty, "%s", buffer);
73 static struct osmocom_ms *get_ms(const char *name, struct vty *vty)
75 struct osmocom_ms *ms;
77 llist_for_each_entry(ms, &ms_list, entity) {
78 if (!strcmp(ms->name, name))
81 vty_out(vty, "MS name '%s' does not exits.%s", name, VTY_NEWLINE);
86 DEFUN(show_ms, show_ms_cmd, "show ms",
87 SHOW_STR "Display available MS entities\n")
89 struct osmocom_ms *ms;
91 llist_for_each_entry(ms, &ms_list, entity) {
92 struct gsm_settings *set = &ms->settings;
94 vty_out(vty, "MS NAME: %s%s", ms->name, VTY_NEWLINE);
95 vty_out(vty, " IMEI: %s%s", set->imei, VTY_NEWLINE);
96 vty_out(vty, " IMEISV: %s%s", set->imeisv, VTY_NEWLINE);
98 vty_out(vty, " IMEI generation: random (%d trailing "
99 "digits)%s", set->imei_random, VTY_NEWLINE);
101 vty_out(vty, " IMEI generation: fixed%s", VTY_NEWLINE);
102 vty_out(vty, " network selection mode: %s%s",
103 (set->plmn_mode == PLMN_MODE_AUTO)
104 ? "automatic" : "manual", VTY_NEWLINE);
110 DEFUN(show_support, show_support_cmd, "show support [ms_name]",
111 SHOW_STR "Display information about MS support\n"
112 "Name of MS (see \"show ms\")")
114 struct osmocom_ms *ms;
117 ms = get_ms(argv[0], vty);
120 gsm_support_dump(&ms->support, print_vty, vty);
122 llist_for_each_entry(ms, &ms_list, entity) {
123 gsm_support_dump(&ms->support, print_vty, vty);
124 vty_out(vty, "%s", VTY_NEWLINE);
131 DEFUN(show_subscr, show_subscr_cmd, "show subscriber [ms_name]",
132 SHOW_STR "Display information about subscriber\n"
133 "Name of MS (see \"show ms\")")
135 struct osmocom_ms *ms;
138 ms = get_ms(argv[0], vty);
141 gsm_subscr_dump(&ms->subscr, print_vty, vty);
143 llist_for_each_entry(ms, &ms_list, entity) {
144 gsm_subscr_dump(&ms->subscr, print_vty, vty);
145 vty_out(vty, "%s", VTY_NEWLINE);
152 DEFUN(show_cell, show_cell_cmd, "show cell MS_NAME",
153 SHOW_STR "Display information about received cells\n"
154 "Name of MS (see \"show ms\")")
156 struct osmocom_ms *ms;
158 ms = get_ms(argv[0], vty);
162 gsm322_dump_cs_list(&ms->cellsel, GSM322_CS_FLAG_SYSINFO, print_vty,
168 DEFUN(show_cell_si, show_cell_si_cmd, "show cell MS_NAME <0-1023>",
169 SHOW_STR "Display information about received cell\n"
170 "Name of MS (see \"show ms\")\nRadio frequency number")
172 struct osmocom_ms *ms;
174 struct gsm48_sysinfo *s;
176 ms = get_ms(argv[0], vty);
181 if (i < 0 || i > 1023) {
182 vty_out(vty, "Given ARFCN '%s' not in range (0..1023)%s",
183 argv[1], VTY_NEWLINE);
186 s = ms->cellsel.list[i].sysinfo;
188 vty_out(vty, "Given ARFCN '%s' has no sysinfo available%s",
189 argv[1], VTY_NEWLINE);
193 gsm48_sysinfo_dump(s, i, print_vty, vty);
198 DEFUN(show_ba, show_ba_cmd, "show ba MS_NAME [mcc] [mnc]",
199 SHOW_STR "Display information about band allocations\n"
200 "Name of MS (see \"show ms\")\nMobile Country Code\n"
201 "Mobile Network Code")
203 struct osmocom_ms *ms;
204 uint16_t mcc = 0, mnc = 0;
206 ms = get_ms(argv[0], vty);
215 gsm322_dump_ba_list(&ms->cellsel, mcc, mnc, print_vty, vty);
220 DEFUN(insert_test, insert_test_cmd, "insert testcard MS_NAME [mcc] [mnc]",
221 "Insert ...\nInsert test card\nName of MS (see \"show ms\")\n"
222 "Mobile Country Code\nMobile Network Code")
224 struct osmocom_ms *ms;
225 uint16_t mcc = 1, mnc = 1;
227 ms = get_ms(argv[0], vty);
231 if (ms->subscr.sim_valid) {
232 vty_out(vty, "Sim already presend, remove first!%s",
242 gsm_subscr_testcard(ms);
247 DEFUN(remove_sim, remove_sim_cmd, "remove sim MS_NAME",
248 "Remove ...\nRemove SIM card\nName of MS (see \"show ms\")")
250 struct osmocom_ms *ms;
252 ms = get_ms(argv[0], vty);
256 if (!ms->subscr.sim_valid) {
257 vty_out(vty, "No Sim inserted!%s", VTY_NEWLINE);
261 gsm_subscr_remove(ms);
266 DEFUN(network_select, network_select_cmd, "network select MS_NAME MCC MNC",
267 "Select ...\nSelect Network\nName of MS (see \"show ms\")\n"
268 "Mobile Country Code\nMobile Network Code")
270 struct osmocom_ms *ms;
271 struct gsm322_plmn *plmn;
273 struct gsm322_msg *ngm;
274 struct gsm322_plmn_list *temp;
278 ms = get_ms(argv[0], vty);
286 llist_for_each_entry(temp, &plmn->sorted_plmn, entry)
287 if (temp->mcc == mcc && temp->mnc == mnc)
290 vty_out(vty, "Network not in list!%s", VTY_NEWLINE);
294 nmsg = gsm322_msgb_alloc(GSM322_EVENT_CHOSE_PLMN);
297 ngm = (struct gsm322_msg *) nmsg->data;
300 gsm322_plmn_sendmsg(ms, nmsg);
305 DEFUN(call, call_cmd, "call MS_NAME (NUMBER|emergency|answer|hangup)",
306 "Make a call\nName of MS (see \"show ms\")\nPhone number to call\n"
307 "Make an emergency call\nAnswer an incomming call\nHangup a call")
309 struct osmocom_ms *ms;
311 ms = get_ms(argv[0], vty);
315 switch (argv[1][0]) {
323 mncc_call(ms, (char *)argv[1]);
329 DEFUN(network_show, network_show_cmd, "network show MS_NAME",
330 "Network ...\nShow results of network search (again)\n"
331 "Name of MS (see \"show ms\")")
333 struct osmocom_ms *ms;
334 struct gsm322_plmn *plmn;
335 struct gsm322_plmn_list *temp;
337 ms = get_ms(argv[0], vty);
342 if (ms->settings.plmn_mode != PLMN_MODE_AUTO
343 && plmn->state != GSM322_M3_NOT_ON_PLMN) {
344 vty_out(vty, "Start network search first!%s", VTY_NEWLINE);
348 llist_for_each_entry(temp, &plmn->sorted_plmn, entry)
349 vty_out(vty, " Network %03d, %02d (%s, %s)%s", temp->mcc,
350 temp->mnc, gsm_get_mcc(temp->mcc),
351 gsm_get_mnc(temp->mcc, temp->mnc), VTY_NEWLINE);
356 DEFUN(network_search, network_search_cmd, "network search MS_NAME",
357 "Network ...\nTrigger network search\nName of MS (see \"show ms\")")
359 struct osmocom_ms *ms;
362 ms = get_ms(argv[0], vty);
366 nmsg = gsm322_msgb_alloc(GSM322_EVENT_USER_RESEL);
369 gsm322_plmn_sendmsg(ms, nmsg);
375 DEFUN(cfg_ms, cfg_ms_cmd, "ms MS_NAME",
376 "Select a mobile station to configure\nName of MS (see \"show ms\")")
378 struct osmocom_ms *ms;
380 ms = get_ms(argv[0], vty);
390 static void config_write_ms_single(struct vty *vty, struct osmocom_ms *ms)
392 struct gsm_settings *set = &ms->settings;
394 vty_out(vty, "ms %s%s", ms->name, VTY_NEWLINE);
395 switch(ms->settings.simtype) {
396 case GSM_SIM_TYPE_NONE:
397 vty_out(vty, " sim none%s", VTY_NEWLINE);
399 case GSM_SIM_TYPE_SLOT:
400 vty_out(vty, " sim slot%s", VTY_NEWLINE);
402 case GSM_SIM_TYPE_TEST:
403 vty_out(vty, " sim test%s", VTY_NEWLINE);
406 vty_out(vty, " network-selection-mode %s%s", (set->plmn_mode
407 == PLMN_MODE_AUTO) ? "auto" : "manual", VTY_NEWLINE);
408 vty_out(vty, " imei %s %s%s", set->imei,
409 set->imeisv + strlen(set->imei), VTY_NEWLINE);
410 if (set->imei_random)
411 vty_out(vty, " imei-random %d%s", set->imei_random,
414 vty_out(vty, " imei-fixed%s", VTY_NEWLINE);
415 vty_out(vty, " test-sim%s", VTY_NEWLINE);
416 vty_out(vty, " imsi %s%s", ms->settings.test_imsi, VTY_NEWLINE);
417 vty_out(vty, " barred-access %s%s", (set->test_barr) ? "yes" : "no",
419 if (ms->settings.test_rplmn_valid)
420 vty_out(vty, " rplmn-valid%s", VTY_NEWLINE);
422 vty_out(vty, " rplmn-invalid%s", VTY_NEWLINE);
423 vty_out(vty, " rplmn %03d %02d%s", ms->settings.test_rplmn_mcc,
424 ms->settings.test_rplmn_mnc, VTY_NEWLINE);
425 vty_out(vty, " hplmn-search %s%s", (set->test_always) ? "everywhere"
426 : "foreign-country", VTY_NEWLINE);
427 vty_out(vty, " exit%s", VTY_NEWLINE);
428 vty_out(vty, "exit%s", VTY_NEWLINE);
429 vty_out(vty, "!%s", VTY_NEWLINE);
432 static int config_write_ms(struct vty *vty)
434 struct osmocom_ms *ms;
436 llist_for_each_entry(ms, &ms_list, entity)
437 config_write_ms_single(vty, ms);
442 DEFUN(cfg_ms_mode, cfg_ms_mode_cmd, "network-selection-mode (auto|manual)",
443 "Set network selection mode\nAutomatic network selection\n"
444 "Manual network selection")
446 struct osmocom_ms *ms = vty->index;
449 if (!ms->plmn.state) {
450 if (argv[0][0] == 'a')
451 ms->settings.plmn_mode = PLMN_MODE_AUTO;
453 ms->settings.plmn_mode = PLMN_MODE_MANUAL;
457 if (argv[0][0] == 'a')
458 nmsg = gsm322_msgb_alloc(GSM322_EVENT_SEL_AUTO);
460 nmsg = gsm322_msgb_alloc(GSM322_EVENT_SEL_MANUAL);
463 gsm322_plmn_sendmsg(ms, nmsg);
468 DEFUN(cfg_ms_imei, cfg_ms_imei_cmd, "imei IMEI [SV]",
469 "Set IMEI (enter without control digit)\n15 Digits IMEI\n"
470 "Software version digit")
472 struct osmocom_ms *ms = vty->index;
473 char *error, *sv = "0";
476 sv = (char *)argv[1];
478 error = gsm_check_imei(argv[0], sv);
480 vty_out(vty, "%s%s", error, VTY_NEWLINE);
484 strcpy(ms->settings.imei, argv[0]);
485 strcpy(ms->settings.imeisv, argv[0]);
486 strcpy(ms->settings.imeisv + 15, sv);
491 DEFUN(cfg_ms_imei_fixed, cfg_ms_imei_fixed_cmd, "imei-fixed",
492 "Use fixed IMEI on every power on")
494 struct osmocom_ms *ms = vty->index;
496 ms->settings.imei_random = 0;
501 DEFUN(cfg_ms_imei_random, cfg_ms_imei_random_cmd, "imei-random <0-15>",
502 "Use random IMEI on every power on\n"
503 "Number of trailing digits to randomize")
505 struct osmocom_ms *ms = vty->index;
507 ms->settings.imei_random = atoi(argv[0]);
512 DEFUN(cfg_ms_sim, cfg_ms_sim_cmd, "sim (none|test)",
513 "Set sim card type when powering on\nNo sim interted\n"
516 struct osmocom_ms *ms = vty->index;
518 switch (argv[0][0]) {
520 ms->settings.simtype = GSM_SIM_TYPE_NONE;
523 ms->settings.simtype = GSM_SIM_TYPE_SLOT;
526 ms->settings.simtype = GSM_SIM_TYPE_TEST;
534 DEFUN(cfg_testsim, cfg_testsim_cmd, "test-sim",
535 "Configure test SIM emulation")
537 vty->node = TESTSIM_NODE;
542 static int config_write_dummy(struct vty *vty)
547 DEFUN(cfg_test_imsi, cfg_test_imsi_cmd, "imsi IMSI",
548 "Set IMSI on test card\n15 Digits IMSI")
550 struct osmocom_ms *ms = vty->index;
552 char *error = gsm_check_imsi(argv[0], &mcc, &mnc);
555 vty_out(vty, "%s%s", error, VTY_NEWLINE);
559 strcpy(ms->settings.test_imsi, argv[0]);
564 DEFUN(cfg_test_barr, cfg_test_barr_cmd, "barred-access (yes|no)",
565 "Allow access to barred cells\nAccess allowed\nAccess denied")
567 struct osmocom_ms *ms = vty->index;
569 switch (argv[0][0]) {
571 ms->settings.test_barr = 1;
574 ms->settings.test_barr = 0;
581 DEFUN(cfg_test_rplmn_valid, cfg_test_rplmn_valid_cmd, "rplmn-valid",
582 "Mark Registered PLMN as valid")
584 struct osmocom_ms *ms = vty->index;
586 ms->settings.test_rplmn_valid = 1;
591 DEFUN(cfg_test_rplmn_invalid, cfg_test_rplmn_invalid_cmd, "rplmn-invalid",
592 "Mark Registered PLMN as invalid")
594 struct osmocom_ms *ms = vty->index;
596 ms->settings.test_rplmn_valid = 0;
601 DEFUN(cfg_test_rplmn, cfg_test_rplmn_cmd, "rplmn MCC MNC",
602 "Set Registered PLMN\nMobile Country Code\nMobile Network Code")
604 struct osmocom_ms *ms = vty->index;
606 ms->settings.test_rplmn_mcc = atoi(argv[0]);
607 ms->settings.test_rplmn_mnc = atoi(argv[1]);
612 DEFUN(cfg_test_hplmn, cfg_test_hplmn_cmd, "hplmn-search (everywhere|foreign-country)",
613 "Set Home PLMN search mode\n"
614 "Search for HPLMN when on any other network\n"
615 "Search for HPLMN when in a different country")
617 struct osmocom_ms *ms = vty->index;
619 switch (argv[0][0]) {
621 ms->settings.test_always = 1;
624 ms->settings.test_always = 0;
631 int ms_vty_init(void)
636 install_element(ENABLE_NODE, &show_ms_cmd);
637 install_element(VIEW_NODE, &show_ms_cmd);
638 install_element(ENABLE_NODE, &show_subscr_cmd);
639 install_element(VIEW_NODE, &show_subscr_cmd);
640 install_element(ENABLE_NODE, &show_support_cmd);
641 install_element(VIEW_NODE, &show_support_cmd);
642 install_element(ENABLE_NODE, &show_cell_cmd);
643 install_element(VIEW_NODE, &show_cell_cmd);
644 install_element(ENABLE_NODE, &show_cell_si_cmd);
645 install_element(VIEW_NODE, &show_cell_si_cmd);
646 install_element(ENABLE_NODE, &show_ba_cmd);
647 install_element(VIEW_NODE, &show_ba_cmd);
649 install_element(ENABLE_NODE, &insert_test_cmd);
650 install_element(ENABLE_NODE, &remove_sim_cmd);
651 install_element(ENABLE_NODE, &network_search_cmd);
652 install_element(ENABLE_NODE, &network_show_cmd);
653 install_element(ENABLE_NODE, &network_select_cmd);
654 install_element(ENABLE_NODE, &call_cmd);
656 install_element(CONFIG_NODE, &cfg_ms_cmd);
657 install_node(&ms_node, config_write_ms);
658 install_default(MS_NODE);
659 install_element(MS_NODE, &cfg_ms_mode_cmd);
660 install_element(MS_NODE, &cfg_ms_imei_cmd);
661 install_element(MS_NODE, &cfg_ms_imei_fixed_cmd);
662 install_element(MS_NODE, &cfg_ms_imei_random_cmd);
663 install_element(MS_NODE, &cfg_ms_sim_cmd);
665 install_element(MS_NODE, &cfg_testsim_cmd);
666 install_node(&testsim_node, config_write_dummy);
667 install_default(TESTSIM_NODE);
668 install_element(TESTSIM_NODE, &cfg_test_imsi_cmd);
669 install_element(TESTSIM_NODE, &cfg_test_barr_cmd);
670 install_element(TESTSIM_NODE, &cfg_test_rplmn_valid_cmd);
671 install_element(TESTSIM_NODE, &cfg_test_rplmn_invalid_cmd);
672 install_element(TESTSIM_NODE, &cfg_test_rplmn_cmd);
673 install_element(TESTSIM_NODE, &cfg_test_hplmn_cmd);