aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/vty_interface_layer3.c
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2009-08-10 10:17:50 +0200
committerHolger Hans Peter Freyther <zecke@selfish.org>2009-08-17 09:52:42 +0200
commitcfa90d41659d2a6d5849c200f441e0ac9edae29b (patch)
treeceb23ffa073c14792ce0763d5a87190311cdbb4e /openbsc/src/vty_interface_layer3.c
parent1494a768c14295a63cbf59f729dcf91a8b4d22ba (diff)
[vty] Move layer3+ functionality to vty_interface_layer3.c
Move everything that is policy, requires access to a DB or is generally in the domain of the MSC to vty_interface_layer3.c.
Diffstat (limited to 'openbsc/src/vty_interface_layer3.c')
-rw-r--r--openbsc/src/vty_interface_layer3.c315
1 files changed, 315 insertions, 0 deletions
diff --git a/openbsc/src/vty_interface_layer3.c b/openbsc/src/vty_interface_layer3.c
new file mode 100644
index 00000000..032e16fc
--- /dev/null
+++ b/openbsc/src/vty_interface_layer3.c
@@ -0,0 +1,315 @@
+/* OpenBSC interface to quagga VTY */
+/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#include <vty/command.h>
+#include <vty/buffer.h>
+#include <vty/vty.h>
+
+#include <arpa/inet.h>
+
+#include <openbsc/linuxlist.h>
+#include <openbsc/gsm_data.h>
+#include <openbsc/gsm_subscriber.h>
+#include <openbsc/gsm_04_11.h>
+#include <openbsc/e1_input.h>
+#include <openbsc/abis_nm.h>
+#include <openbsc/gsm_utils.h>
+#include <openbsc/db.h>
+#include <openbsc/talloc.h>
+
+/* forward declarations */
+void subscr_dump_vty(struct vty *vty, struct gsm_subscriber *subscr);
+
+static struct gsm_network *gsmnet;
+
+struct cmd_node subscr_node = {
+ SUBSCR_NODE,
+ "%s(subscriber)#",
+ 1,
+};
+
+static int dummy_config_write(struct vty *v)
+{
+ return CMD_SUCCESS;
+}
+
+
+static struct buffer *argv_to_buffer(int argc, const char *argv[], int base)
+{
+ struct buffer *b = buffer_new(1024);
+ int i;
+
+ if (!b)
+ return NULL;
+
+ for (i = base; i < argc; i++) {
+ buffer_putstr(b, argv[i]);
+ buffer_putc(b, ' ');
+ }
+ buffer_putc(b, '\0');
+
+ return b;
+}
+
+/* per-subscriber configuration */
+DEFUN(cfg_subscr,
+ cfg_subscr_cmd,
+ "subscriber IMSI",
+ "Select a Subscriber to configure\n")
+{
+ const char *imsi = argv[0];
+ struct gsm_subscriber *subscr;
+
+ subscr = subscr_get_by_imsi(gsmnet, imsi);
+ if (!subscr) {
+ vty_out(vty, "%% No subscriber for IMSI %s%s",
+ imsi, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ vty->index = subscr;
+ vty->node = SUBSCR_NODE;
+
+ return CMD_SUCCESS;
+}
+
+/* Subscriber */
+DEFUN(show_subscr,
+ show_subscr_cmd,
+ "show subscriber [IMSI]",
+ SHOW_STR "Display information about a subscriber\n")
+{
+ const char *imsi;
+ struct gsm_subscriber *subscr;
+
+ if (argc >= 1) {
+ imsi = argv[0];
+ subscr = subscr_get_by_imsi(gsmnet, imsi);
+ if (!subscr) {
+ vty_out(vty, "%% unknown subscriber%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ subscr_dump_vty(vty, subscr);
+
+ return CMD_SUCCESS;
+ }
+
+ /* FIXME: iterate over all subscribers ? */
+ return CMD_WARNING;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(show_subscr_cache,
+ show_subscr_cache_cmd,
+ "show subscriber cache",
+ SHOW_STR "Display contents of subscriber cache\n")
+{
+ struct gsm_subscriber *subscr;
+
+ llist_for_each_entry(subscr, &active_subscribers, entry) {
+ vty_out(vty, " Subscriber:%s", VTY_NEWLINE);
+ subscr_dump_vty(vty, subscr);
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(sms_send_pend,
+ sms_send_pend_cmd,
+ "sms send pending MIN_ID",
+ "Send all pending SMS starting from MIN_ID")
+{
+ struct gsm_sms *sms;
+ int id = atoi(argv[0]);
+
+ while (1) {
+ sms = db_sms_get_unsent(gsmnet, id++);
+ if (!sms)
+ return CMD_WARNING;
+
+ if (!sms->receiver) {
+ sms_free(sms);
+ continue;
+ }
+
+ gsm411_send_sms_subscr(sms->receiver, sms);
+ }
+
+ return CMD_SUCCESS;
+}
+
+struct gsm_sms *sms_from_text(struct gsm_subscriber *receiver, const char *text)
+{
+ struct gsm_sms *sms = sms_alloc();
+
+ if (!sms)
+ return NULL;
+
+ if (!receiver->lac) {
+ /* subscriber currently not attached, store in database? */
+ return NULL;
+ }
+
+ sms->receiver = subscr_get(receiver);
+ strncpy(sms->text, text, sizeof(sms->text)-1);
+
+ /* FIXME: don't use ID 1 static */
+ sms->sender = subscr_get_by_id(gsmnet, 1);
+ sms->reply_path_req = 0;
+ sms->status_rep_req = 0;
+ sms->ud_hdr_ind = 0;
+ sms->protocol_id = 0; /* implicit */
+ sms->data_coding_scheme = 0; /* default 7bit */
+ strncpy(sms->dest_addr, receiver->extension, sizeof(sms->dest_addr)-1);
+ /* Generate user_data */
+ sms->user_data_len = gsm_7bit_encode(sms->user_data, sms->text);
+
+ return sms;
+}
+
+static int _send_sms_buffer(struct gsm_subscriber *receiver,
+ struct buffer *b)
+{
+ struct gsm_sms *sms;
+
+ sms = sms_from_text(receiver, buffer_getstr(b));
+
+ gsm411_send_sms_subscr(receiver, sms);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(sms_send_ext,
+ sms_send_ext_cmd,
+ "sms send extension EXTEN .LINE",
+ "Send a message to a subscriber identified by EXTEN")
+{
+ struct gsm_subscriber *receiver;
+ struct buffer *b;
+ int rc;
+
+ receiver = subscr_get_by_extension(gsmnet, argv[0]);
+ if (!receiver)
+ return CMD_WARNING;
+
+ b = argv_to_buffer(argc, argv, 1);
+ rc = _send_sms_buffer(receiver, b);
+ buffer_free(b);
+
+ return rc;
+}
+
+DEFUN(sms_send_imsi,
+ sms_send_imsi_cmd,
+ "sms send imsi IMSI .LINE",
+ "Send a message to a subscriber identified by IMSI")
+{
+ struct gsm_subscriber *receiver;
+ struct buffer *b;
+ int rc;
+
+ receiver = subscr_get_by_imsi(gsmnet, argv[0]);
+ if (!receiver)
+ return CMD_WARNING;
+
+ b = argv_to_buffer(argc, argv, 1);
+ rc = _send_sms_buffer(receiver, b);
+ buffer_free(b);
+
+ return rc;
+}
+
+
+DEFUN(cfg_subscr_name,
+ cfg_subscr_name_cmd,
+ "name NAME",
+ "Set the name of the subscriber")
+{
+ const char *name = argv[0];
+ struct gsm_subscriber *subscr = vty->index;
+
+ strncpy(subscr->name, name, sizeof(subscr->name));
+
+ db_sync_subscriber(subscr);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_subscr_extension,
+ cfg_subscr_extension_cmd,
+ "extension EXTENSION",
+ "Set the extension of the subscriber")
+{
+ const char *name = argv[0];
+ struct gsm_subscriber *subscr = vty->index;
+
+ strncpy(subscr->extension, name, sizeof(subscr->extension));
+
+ db_sync_subscriber(subscr);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_subscr_authorized,
+ cfg_subscr_authorized_cmd,
+ "auth <0-1>",
+ "Set the authorization status of the subscriber")
+{
+ int auth = atoi(argv[0]);
+ struct gsm_subscriber *subscr = vty->index;
+
+ if (auth)
+ subscr->authorized = 1;
+ else
+ subscr->authorized = 0;
+
+ db_sync_subscriber(subscr);
+
+ return CMD_SUCCESS;
+}
+
+
+int bsc_vty_init_extra(struct gsm_network *net)
+{
+ gsmnet = net;
+
+ install_element(VIEW_NODE, &show_subscr_cmd);
+ install_element(VIEW_NODE, &show_subscr_cache_cmd);
+
+ install_element(VIEW_NODE, &sms_send_pend_cmd);
+ install_element(VIEW_NODE, &sms_send_ext_cmd);
+ install_element(VIEW_NODE, &sms_send_imsi_cmd);
+
+ install_element(CONFIG_NODE, &cfg_subscr_cmd);
+ install_node(&subscr_node, dummy_config_write);
+
+ install_default(SUBSCR_NODE);
+ install_element(SUBSCR_NODE, &cfg_subscr_name_cmd);
+ install_element(SUBSCR_NODE, &cfg_subscr_extension_cmd);
+ install_element(SUBSCR_NODE, &cfg_subscr_authorized_cmd);
+
+ return 0;
+}