blob: 032e16fc42ade43a78d5935433606c92bbd61c98 [file] [log] [blame]
Holger Hans Peter Freythercfa90d42009-08-10 10:17:50 +02001/* OpenBSC interface to quagga VTY */
2/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
3 * All Rights Reserved
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 */
20
21#include <stdlib.h>
22#include <unistd.h>
23#include <sys/types.h>
24
25#include <vty/command.h>
26#include <vty/buffer.h>
27#include <vty/vty.h>
28
29#include <arpa/inet.h>
30
31#include <openbsc/linuxlist.h>
32#include <openbsc/gsm_data.h>
33#include <openbsc/gsm_subscriber.h>
34#include <openbsc/gsm_04_11.h>
35#include <openbsc/e1_input.h>
36#include <openbsc/abis_nm.h>
37#include <openbsc/gsm_utils.h>
38#include <openbsc/db.h>
39#include <openbsc/talloc.h>
40
41/* forward declarations */
42void subscr_dump_vty(struct vty *vty, struct gsm_subscriber *subscr);
43
44static struct gsm_network *gsmnet;
45
46struct cmd_node subscr_node = {
47 SUBSCR_NODE,
48 "%s(subscriber)#",
49 1,
50};
51
52static int dummy_config_write(struct vty *v)
53{
54 return CMD_SUCCESS;
55}
56
57
58static struct buffer *argv_to_buffer(int argc, const char *argv[], int base)
59{
60 struct buffer *b = buffer_new(1024);
61 int i;
62
63 if (!b)
64 return NULL;
65
66 for (i = base; i < argc; i++) {
67 buffer_putstr(b, argv[i]);
68 buffer_putc(b, ' ');
69 }
70 buffer_putc(b, '\0');
71
72 return b;
73}
74
75/* per-subscriber configuration */
76DEFUN(cfg_subscr,
77 cfg_subscr_cmd,
78 "subscriber IMSI",
79 "Select a Subscriber to configure\n")
80{
81 const char *imsi = argv[0];
82 struct gsm_subscriber *subscr;
83
84 subscr = subscr_get_by_imsi(gsmnet, imsi);
85 if (!subscr) {
86 vty_out(vty, "%% No subscriber for IMSI %s%s",
87 imsi, VTY_NEWLINE);
88 return CMD_WARNING;
89 }
90
91 vty->index = subscr;
92 vty->node = SUBSCR_NODE;
93
94 return CMD_SUCCESS;
95}
96
97/* Subscriber */
98DEFUN(show_subscr,
99 show_subscr_cmd,
100 "show subscriber [IMSI]",
101 SHOW_STR "Display information about a subscriber\n")
102{
103 const char *imsi;
104 struct gsm_subscriber *subscr;
105
106 if (argc >= 1) {
107 imsi = argv[0];
108 subscr = subscr_get_by_imsi(gsmnet, imsi);
109 if (!subscr) {
110 vty_out(vty, "%% unknown subscriber%s",
111 VTY_NEWLINE);
112 return CMD_WARNING;
113 }
114 subscr_dump_vty(vty, subscr);
115
116 return CMD_SUCCESS;
117 }
118
119 /* FIXME: iterate over all subscribers ? */
120 return CMD_WARNING;
121
122 return CMD_SUCCESS;
123}
124
125DEFUN(show_subscr_cache,
126 show_subscr_cache_cmd,
127 "show subscriber cache",
128 SHOW_STR "Display contents of subscriber cache\n")
129{
130 struct gsm_subscriber *subscr;
131
132 llist_for_each_entry(subscr, &active_subscribers, entry) {
133 vty_out(vty, " Subscriber:%s", VTY_NEWLINE);
134 subscr_dump_vty(vty, subscr);
135 }
136
137 return CMD_SUCCESS;
138}
139
140DEFUN(sms_send_pend,
141 sms_send_pend_cmd,
142 "sms send pending MIN_ID",
143 "Send all pending SMS starting from MIN_ID")
144{
145 struct gsm_sms *sms;
146 int id = atoi(argv[0]);
147
148 while (1) {
149 sms = db_sms_get_unsent(gsmnet, id++);
150 if (!sms)
151 return CMD_WARNING;
152
153 if (!sms->receiver) {
154 sms_free(sms);
155 continue;
156 }
157
158 gsm411_send_sms_subscr(sms->receiver, sms);
159 }
160
161 return CMD_SUCCESS;
162}
163
164struct gsm_sms *sms_from_text(struct gsm_subscriber *receiver, const char *text)
165{
166 struct gsm_sms *sms = sms_alloc();
167
168 if (!sms)
169 return NULL;
170
171 if (!receiver->lac) {
172 /* subscriber currently not attached, store in database? */
173 return NULL;
174 }
175
176 sms->receiver = subscr_get(receiver);
177 strncpy(sms->text, text, sizeof(sms->text)-1);
178
179 /* FIXME: don't use ID 1 static */
180 sms->sender = subscr_get_by_id(gsmnet, 1);
181 sms->reply_path_req = 0;
182 sms->status_rep_req = 0;
183 sms->ud_hdr_ind = 0;
184 sms->protocol_id = 0; /* implicit */
185 sms->data_coding_scheme = 0; /* default 7bit */
186 strncpy(sms->dest_addr, receiver->extension, sizeof(sms->dest_addr)-1);
187 /* Generate user_data */
188 sms->user_data_len = gsm_7bit_encode(sms->user_data, sms->text);
189
190 return sms;
191}
192
193static int _send_sms_buffer(struct gsm_subscriber *receiver,
194 struct buffer *b)
195{
196 struct gsm_sms *sms;
197
198 sms = sms_from_text(receiver, buffer_getstr(b));
199
200 gsm411_send_sms_subscr(receiver, sms);
201
202 return CMD_SUCCESS;
203}
204
205DEFUN(sms_send_ext,
206 sms_send_ext_cmd,
207 "sms send extension EXTEN .LINE",
208 "Send a message to a subscriber identified by EXTEN")
209{
210 struct gsm_subscriber *receiver;
211 struct buffer *b;
212 int rc;
213
214 receiver = subscr_get_by_extension(gsmnet, argv[0]);
215 if (!receiver)
216 return CMD_WARNING;
217
218 b = argv_to_buffer(argc, argv, 1);
219 rc = _send_sms_buffer(receiver, b);
220 buffer_free(b);
221
222 return rc;
223}
224
225DEFUN(sms_send_imsi,
226 sms_send_imsi_cmd,
227 "sms send imsi IMSI .LINE",
228 "Send a message to a subscriber identified by IMSI")
229{
230 struct gsm_subscriber *receiver;
231 struct buffer *b;
232 int rc;
233
234 receiver = subscr_get_by_imsi(gsmnet, argv[0]);
235 if (!receiver)
236 return CMD_WARNING;
237
238 b = argv_to_buffer(argc, argv, 1);
239 rc = _send_sms_buffer(receiver, b);
240 buffer_free(b);
241
242 return rc;
243}
244
245
246DEFUN(cfg_subscr_name,
247 cfg_subscr_name_cmd,
248 "name NAME",
249 "Set the name of the subscriber")
250{
251 const char *name = argv[0];
252 struct gsm_subscriber *subscr = vty->index;
253
254 strncpy(subscr->name, name, sizeof(subscr->name));
255
256 db_sync_subscriber(subscr);
257
258 return CMD_SUCCESS;
259}
260
261DEFUN(cfg_subscr_extension,
262 cfg_subscr_extension_cmd,
263 "extension EXTENSION",
264 "Set the extension of the subscriber")
265{
266 const char *name = argv[0];
267 struct gsm_subscriber *subscr = vty->index;
268
269 strncpy(subscr->extension, name, sizeof(subscr->extension));
270
271 db_sync_subscriber(subscr);
272
273 return CMD_SUCCESS;
274}
275
276DEFUN(cfg_subscr_authorized,
277 cfg_subscr_authorized_cmd,
278 "auth <0-1>",
279 "Set the authorization status of the subscriber")
280{
281 int auth = atoi(argv[0]);
282 struct gsm_subscriber *subscr = vty->index;
283
284 if (auth)
285 subscr->authorized = 1;
286 else
287 subscr->authorized = 0;
288
289 db_sync_subscriber(subscr);
290
291 return CMD_SUCCESS;
292}
293
294
295int bsc_vty_init_extra(struct gsm_network *net)
296{
297 gsmnet = net;
298
299 install_element(VIEW_NODE, &show_subscr_cmd);
300 install_element(VIEW_NODE, &show_subscr_cache_cmd);
301
302 install_element(VIEW_NODE, &sms_send_pend_cmd);
303 install_element(VIEW_NODE, &sms_send_ext_cmd);
304 install_element(VIEW_NODE, &sms_send_imsi_cmd);
305
306 install_element(CONFIG_NODE, &cfg_subscr_cmd);
307 install_node(&subscr_node, dummy_config_write);
308
309 install_default(SUBSCR_NODE);
310 install_element(SUBSCR_NODE, &cfg_subscr_name_cmd);
311 install_element(SUBSCR_NODE, &cfg_subscr_extension_cmd);
312 install_element(SUBSCR_NODE, &cfg_subscr_authorized_cmd);
313
314 return 0;
315}