blob: ad496da79afd4bce6f70612da5782b6032b9f967 [file] [log] [blame]
Harald Welte338e3b32012-11-20 22:22:04 +01001/* SMPP vty interface */
2
3/* (C) 2012 by Harald Welte <laforge@gnumonks.org>
4 * All Rights Reserved
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
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 Affero General Public License for more details.
15 *
16 * You should have received a copy of the GNU Affero General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
21#include <string.h>
22#include <netdb.h>
23#include <sys/socket.h>
24
25#include <osmocom/vty/command.h>
26#include <osmocom/vty/buffer.h>
27#include <osmocom/vty/vty.h>
28
29#include <osmocom/core/linuxlist.h>
30#include <osmocom/core/utils.h>
31#include <osmocom/core/talloc.h>
32
33#include <openbsc/vty.h>
34
35#include "smpp_smsc.h"
36
37struct smsc *smsc_from_vty(struct vty *v);
38
39static struct cmd_node smpp_node = {
40 SMPP_NODE,
41 "%s(config-smpp)# ",
42 1,
43};
44
45static struct cmd_node esme_node = {
46 SMPP_ESME_NODE,
47 "%s(config-smpp-esme)# ",
48 1,
49};
50
51DEFUN(cfg_smpp, cfg_smpp_cmd,
52 "smpp", "Configure SMPP SMS Interface")
53{
54 vty->node = SMPP_NODE;
55
56 return CMD_SUCCESS;
57}
58
59DEFUN(cfg_smpp_port, cfg_smpp_port_cmd,
60 "local-tcp-port <1-65535>",
61 "Set the local TCP port on which we listen for SMPP\n"
62 "TCP port number")
63{
64 struct smsc *smsc = smsc_from_vty(vty);
65 uint16_t port = atoi(argv[0]);
66 int rc;
67
68 rc = smpp_smsc_init(smsc, port);
69 if (rc < 0) {
70 vty_out(vty, "%% Cannot bind to new port %u nor to "
71 "old port %u%s", port, smsc->listen_port, VTY_NEWLINE);
72 return CMD_WARNING;
73 }
74
75 if (port != smsc->listen_port) {
76 vty_out(vty, "%% Cannot bind to new port %u, staying on old"
77 "port %u%s", port, smsc->listen_port, VTY_NEWLINE);
78 return CMD_WARNING;
79 }
80
81 return CMD_SUCCESS;
82}
83
84DEFUN(cfg_smpp_sys_id, cfg_smpp_sys_id_cmd,
85 "system-id ID", "Set the System ID of this SMSC")
86{
87 struct smsc *smsc = smsc_from_vty(vty);
88
89 if (strlen(argv[0])+1 > sizeof(smsc->system_id))
90 return CMD_WARNING;
91
92 strcpy(smsc->system_id, argv[0]);
93
94 return CMD_SUCCESS;
95}
96
97DEFUN(cfg_smpp_policy, cfg_smpp_policy_cmd,
98 "policy (accept-all|closed)",
99 "Set the authentication policy of this SMSC\n"
100 "Accept all SMPP connections independeint of system ID / passwd\n"
101 "Accept only SMPP connections from ESMEs explicitly configured")
102{
103 struct smsc *smsc = smsc_from_vty(vty);
104
105 if (!strcmp(argv[0], "accept-all"))
106 smsc->accept_all = 1;
107 else
108 smsc->accept_all = 0;
109
110 return CMD_SUCCESS;
111}
112
113
114static int config_write_smpp(struct vty *vty)
115{
116 struct smsc *smsc = smsc_from_vty(vty);
117
118 vty_out(vty, "smpp%s", VTY_NEWLINE);
119 vty_out(vty, " local-tcp-port %u%s", smsc->listen_port, VTY_NEWLINE);
120 vty_out(vty, " system-id %s%s", smsc->system_id, VTY_NEWLINE);
121 vty_out(vty, " policy %s%s",
122 smsc->accept_all ? "accept-all" : "closed", VTY_NEWLINE);
123
124 return CMD_SUCCESS;
125}
126
127DEFUN(cfg_esme, cfg_esme_cmd,
128 "esme NAME", "Configure a particular ESME")
129{
130 struct smsc *smsc = smsc_from_vty(vty);
131 struct osmo_smpp_acl *acl;
132 const char *id = argv[0];
133
134 if (strlen(id) > 16) {
135 vty_out(vty, "%% System ID cannot be more than 16 "
136 "characters long%s", VTY_NEWLINE);
137 return CMD_WARNING;
138 }
139 acl = smpp_acl_by_system_id(smsc, id);
140 if (!acl) {
141 acl = smpp_acl_alloc(smsc, id);
142 if (!acl)
143 return CMD_WARNING;
144 }
145
146 vty->index = acl;
147 vty->index_sub = &acl->description;
148 vty->node = SMPP_ESME_NODE;
149
150 return CMD_SUCCESS;
151}
152
153DEFUN(cfg_no_esme, cfg_no_esme_cmd,
154 "no esme NAME", NO_STR "Remove ESME configuration")
155{
156 struct smsc *smsc = smsc_from_vty(vty);
157 struct osmo_smpp_acl *acl;
158 const char *id = argv[0];
159
160 acl = smpp_acl_by_system_id(smsc, id);
161 if (!acl) {
162 vty_out(vty, "%% ESME with system id '%s' unknown%s",
163 id, VTY_NEWLINE);
164 return CMD_WARNING;
165 }
166
167 /* FIXME: close the connection, free data structure, etc. */
168
169 smpp_acl_delete(acl);
170
171 return CMD_SUCCESS;
172}
173
174
175DEFUN(cfg_esme_passwd, cfg_esme_passwd_cmd,
176 "password PASSWORD", "Set the password for this ESME")
177{
178 struct osmo_smpp_acl *acl = vty->index;
179
180 if (strlen(argv[0])+1 > sizeof(acl->passwd))
181 return CMD_WARNING;
182
183 strcpy(acl->passwd, argv[0]);
184
185 return CMD_SUCCESS;
186}
187
188DEFUN(cfg_esme_no_passwd, cfg_esme_no_passwd_cmd,
189 "no password", NO_STR "Set the password for this ESME")
190{
191 struct osmo_smpp_acl *acl = vty->index;
192
193 memset(acl->passwd, 0, sizeof(acl->passwd));
194
195 return CMD_SUCCESS;
196}
197
198DEFUN(cfg_esme_route, cfg_esme_route_cmd,
199 "route DESTINATION",
200 "Configure a route for MO-SMS to be sent to this ESME\n"
201 "Destination phone number")
202{
203 struct osmo_smpp_acl *acl = vty->index;
204
205 /* FIXME: check if DESTINATION is all-digits */
206
207 return CMD_SUCCESS;
208}
209
210DEFUN(cfg_esme_defaultroute, cfg_esme_defaultroute_cmd,
211 "default-route",
212 "Set this ESME as default-route for all SMS to unknown destinations")
213{
214 struct osmo_smpp_acl *acl = vty->index;
215
216 acl->default_route = 1;
217
218 return CMD_SUCCESS;
219}
220
221DEFUN(cfg_no_esme_defaultroute, cfg_esme_no_defaultroute_cmd,
222 "no default-route", NO_STR
223 "Set this ESME as default-route for all SMS to unknown destinations")
224{
225 struct osmo_smpp_acl *acl = vty->index;
226
227 acl->default_route = 0;
228
229 /* remove currently active default route, if it was created by
230 * this ACL */
231 if (acl->smsc->def_route && acl->smsc->def_route->acl == acl)
232 acl->smsc->def_route = NULL;
233
234 return CMD_SUCCESS;
235}
236
237static void dump_one_esme(struct vty *vty, struct osmo_esme *esme)
238{
239 char host[128], serv[128];
240
241 host[0] = 0;
242 serv[0] = 0;
243 getnameinfo((const struct sockaddr *) &esme->sa, esme->sa_len,
244 host, sizeof(host), serv, sizeof(serv), NI_NUMERICSERV);
245
246 vty_out(vty, "ESME System ID: %s, Password: %s, SMPP Version %02x%s",
247 esme->system_id, esme->acl->passwd, esme->smpp_version, VTY_NEWLINE);
248 vty_out(vty, " Connected from: %s:%s%s", host, serv, VTY_NEWLINE);
249}
250
251DEFUN(show_esme, show_esme_cmd,
252 "show smpp esme",
253 SHOW_STR "SMPP Interface\n" "SMPP Extrenal SMS Entity\n")
254{
255 struct smsc *smsc = smsc_from_vty(vty);
256 struct osmo_esme *esme;
257
258 llist_for_each_entry(esme, &smsc->esme_list, list)
259 dump_one_esme(vty, esme);
260
261 return CMD_SUCCESS;
262}
263
264static void config_write_esme_single(struct vty *vty, struct osmo_smpp_acl *acl)
265{
266 vty_out(vty, " esme %s%s", acl->system_id, VTY_NEWLINE);
267 if (strlen(acl->passwd))
268 vty_out(vty, " password %s%s", acl->passwd, VTY_NEWLINE);
269 if (acl->default_route)
270 vty_out(vty, " default-route%s", VTY_NEWLINE);
271}
272
273static int config_write_esme(struct vty *v)
274{
275 struct smsc *smsc = smsc_from_vty(v);
276 struct osmo_smpp_acl *acl;
277
278 llist_for_each_entry(acl, &smsc->acl_list, list)
279 config_write_esme_single(v, acl);
280
281 return CMD_SUCCESS;
282}
283
284int smpp_vty_init(void)
285{
286 install_node(&smpp_node, config_write_smpp);
287 install_default(SMPP_NODE);
288 install_element(CONFIG_NODE, &cfg_smpp_cmd);
289
290 install_element(SMPP_NODE, &cfg_smpp_port_cmd);
291 install_element(SMPP_NODE, &cfg_smpp_sys_id_cmd);
292 install_element(SMPP_NODE, &cfg_smpp_policy_cmd);
293 install_element(SMPP_NODE, &cfg_esme_cmd);
294 install_element(SMPP_NODE, &cfg_no_esme_cmd);
295
296 install_node(&esme_node, config_write_esme);
297 install_default(SMPP_ESME_NODE);
298 install_element(SMPP_ESME_NODE, &cfg_esme_passwd_cmd);
299 install_element(SMPP_ESME_NODE, &cfg_esme_no_passwd_cmd);
300 install_element(SMPP_ESME_NODE, &cfg_esme_route_cmd);
301 install_element(SMPP_ESME_NODE, &cfg_esme_defaultroute_cmd);
302 install_element(SMPP_ESME_NODE, &cfg_esme_no_defaultroute_cmd);
303 install_element(SMPP_ESME_NODE, &ournode_exit_cmd);
304
305 install_element_ve(&show_esme_cmd);
306
307 return 0;
308}