1 /*
2 * Various lcr related functions :: RPC API
3 *
4 * Copyright (C) 2009-2010 Juha Heinanen
5 *
6 * This file is part of Kamailio, a free SIP server.
7 *
8 * Kamailio is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version
12 *
13 * Kamailio is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 /*!
24 * \file
25 * \brief Kamailio lcr :: rpc API interface
26 * \ingroup lcr
27 * Module: \ref lcr
28 */
29
30 #include "lcr_rpc.h"
31
32 #include "lcr_mod.h"
33 #include "../../core/ip_addr.h"
34
35
36 static const char *reload_doc[2] = {"Reload lcr tables from database.", 0};
37
38
reload(rpc_t * rpc,void * c)39 static void reload(rpc_t *rpc, void *c)
40 {
41 lock_get(reload_lock);
42 if(reload_tables() != 1)
43 rpc->fault(c, 500, "LCR Module Reload Failed");
44 lock_release(reload_lock);
45 }
46
47
48 static const char *dump_gws_doc[2] = {"Dump the contents of lcr_gws table.", 0};
49
50
dump_gw(rpc_t * rpc,void * st,struct gw_info * gw,unsigned int gw_index,unsigned int lcr_id)51 static void dump_gw(rpc_t *rpc, void *st, struct gw_info *gw, unsigned int gw_index, unsigned int lcr_id)
52 {
53 str scheme, gw_name, hostname, params, transport;
54 str prefix, tag;
55 char buf[INT2STR_MAX_LEN], *start;
56 int len;
57
58 rpc->struct_add(st, "d", "lcr_id", lcr_id);
59 rpc->struct_add(st, "d", "gw_index", gw_index);
60 rpc->struct_add(st, "d", "gw_id", gw->gw_id);
61 gw_name.s = gw->gw_name;
62 gw_name.len = gw->gw_name_len;
63 rpc->struct_add(st, "S", "gw_name", &gw_name);
64 scheme.s = gw->scheme;
65 scheme.len = gw->scheme_len;
66 rpc->struct_add(st, "S", "scheme", &scheme);
67 switch(gw->ip_addr.af) {
68 case AF_INET:
69 rpc->struct_printf(st, "ip_addr", "%d.%d.%d.%d",
70 gw->ip_addr.u.addr[0], gw->ip_addr.u.addr[1],
71 gw->ip_addr.u.addr[2], gw->ip_addr.u.addr[3]);
72 break;
73 case AF_INET6:
74 rpc->struct_printf(st, "ip_addr", "%x:%x:%x:%x:%x:%x:%x:%x",
75 gw->ip_addr.u.addr16[0],
76 gw->ip_addr.u.addr16[1],
77 gw->ip_addr.u.addr16[2],
78 gw->ip_addr.u.addr16[3],
79 gw->ip_addr.u.addr16[4],
80 gw->ip_addr.u.addr16[5],
81 gw->ip_addr.u.addr16[6],
82 gw->ip_addr.u.addr16[7]);
83 break;
84 case 0:
85 rpc->struct_add(st, "s", "ip_addr", "0.0.0.0");
86 break;
87 }
88 hostname.s = gw->hostname;
89 hostname.len = gw->hostname_len;
90 rpc->struct_add(st, "S", "hostname", &hostname);
91 rpc->struct_add(st, "d", "port", gw->port);
92 params.s = gw->params;
93 params.len = gw->params_len;
94 rpc->struct_add(st, "S", "params", ¶ms);
95 transport.s = gw->transport;
96 transport.len = gw->transport_len;
97 rpc->struct_add(st, "S", "transport", &transport);
98 prefix.s = gw->prefix;
99 prefix.len = gw->prefix_len;
100 tag.s = gw->tag;
101 tag.len = gw->tag_len;
102 start = int2strbuf(
103 gw->defunct_until, &(buf[0]), INT2STR_MAX_LEN, &len);
104 rpc->struct_add(st, "dSSdds", "strip", gw->strip, "prefix",
105 &prefix, "tag", &tag, "flags", gw->flags, "state",
106 gw->state, "defunct_until", start);
107 }
108
dump_gws(rpc_t * rpc,void * c)109 static void dump_gws(rpc_t *rpc, void *c)
110 {
111 void *st;
112 void *rec = NULL;
113 void *srec = NULL;
114 unsigned int i, j;
115 struct gw_info *gws;
116
117 for(j = 1; j <= lcr_count_param; j++) {
118
119 gws = gw_pt[j];
120
121 for(i = 1; i <= gws[0].ip_addr.u.addr32[0]; i++) {
122 if (srec==NULL) {
123 /* We create one array per lcr_id */
124 if(rpc->add(c, "{", &rec) < 0)
125 return;
126 if(rpc->struct_add(rec, "[", "gw", &srec) < 0)
127 return;
128 }
129 if(rpc->array_add(srec, "{", &st) < 0)
130 return;
131 dump_gw(rpc, st, &gws[i], i, j);
132 }
133 }
134 }
135
136
137 static const char *dump_rules_doc[2] = {
138 "Dump the contents of the lcr_rules table.", 0};
139
140
dump_rules(rpc_t * rpc,void * c)141 static void dump_rules(rpc_t *rpc, void *c)
142 {
143 int i, j;
144 int _filter_by_prefix = 0;
145 int _lcr_id = 0;
146 str _prefix = {NULL,0};
147 struct rule_info **rules, *rule;
148 struct target *t;
149 void *rec = NULL;
150 void *srec = NULL;
151 void *st, *sst, *ssst;
152 str prefix, from_uri, request_uri;
153
154 if (rpc->scan(c, "d", &_lcr_id)>0) {
155 if (rpc->scan(c, ".S", &_prefix)>0) {
156 _filter_by_prefix = 1;
157 }
158 }
159
160 for(j = 1; j <= lcr_count_param; j++) {
161
162 if (_lcr_id && _lcr_id!=j) continue;
163
164 rules = rule_pt[j];
165
166 for(i = 0; i < lcr_rule_hash_size_param; i++) {
167 rule = rules[i];
168 while(rule) {
169 if (_filter_by_prefix && _prefix.len && _prefix.s) {
170 if (_prefix.len < rule->prefix_len ||
171 strncmp(_prefix.s, rule->prefix, rule->prefix_len)!=0) {
172 rule = rule->next;
173 continue;
174 }
175 }
176 if (srec==NULL) {
177 /* We create one array per lcr_id */
178 if(rpc->add(c, "{", &rec) < 0)
179 return;
180 if(rpc->struct_add(rec, "[", "rule", &srec) < 0)
181 return;
182 }
183 if(rpc->array_add(srec, "{", &st) < 0)
184 return;
185 prefix.s = rule->prefix;
186 prefix.len = rule->prefix_len;
187 from_uri.s = rule->from_uri;
188 from_uri.len = rule->from_uri_len;
189 request_uri.s = rule->request_uri;
190 request_uri.len = rule->request_uri_len;
191 rpc->struct_add(st, "ddSSSd", "lcr_id", j, "rule_id",
192 rule->rule_id, "prefix", &prefix, "from_uri", &from_uri,
193 "request_uri", &request_uri, "stopper", rule->stopper);
194 t = rule->targets;
195 if (t) {
196 if (rpc->struct_add(st, "[", "gw", &sst) < 0)
197 return;
198 while(t) {
199 if (rpc->array_add(sst, "{", &ssst) < 0)
200 return;
201 rpc->struct_add(ssst, "ddd", "gw_index", t->gw_index,
202 "priority", t->priority, "weight", t->weight);
203 t = t->next;
204 }
205 }
206 rule = rule->next;
207 }
208 }
209
210 /* Mark the end of rule array */
211 srec = NULL;
212
213 if (_filter_by_prefix)
214 continue;
215 rule = rules[lcr_rule_hash_size_param];
216 if (rule) {
217 if(rpc->struct_add(rec, "[", "prefix_len", &st) < 0)
218 return;
219 while(rule) {
220 rpc->array_add(st, "d", rule->prefix_len);
221 rule = rule->next;
222 }
223 }
224 }
225 if (rec==NULL) rpc->fault(c, 404, "Empty reply");
226 }
227
228
229 static const char *defunct_gw_doc[2] = {
230 "Defunct gateway until specified time (Unix timestamp).", 0};
231
232
defunct_gw(rpc_t * rpc,void * c)233 static void defunct_gw(rpc_t *rpc, void *c)
234 {
235 unsigned int lcr_id, gw_id, until;
236
237 if(rpc->scan(c, "ddd", &lcr_id, &gw_id, &until) < 3) {
238 rpc->fault(c, 400, "lcr_id, gw_id, and timestamp parameters required");
239 return;
240 }
241
242 if(rpc_defunct_gw(lcr_id, gw_id, until) == 0) {
243 rpc->fault(c, 400, "parameter value error (see syslog)");
244 }
245
246 return;
247 }
248
249 static const char *load_gws_doc[2] = {
250 "Load matching gateways and prints their info in priority order. "
251 "Mandatory parameters are lcr_id and uri_user followed by optional "
252 "parameters caller_uri and request_uri. Error is reported if an "
253 "lcr_rule with matching prefix and from_uri has non-null request_uri "
254 "and request_uri parameter has not been given.",
255 0};
256
257
load_gws(rpc_t * rpc,void * c)258 static void load_gws(rpc_t *rpc, void *c)
259 {
260 unsigned int lcr_id, i, j;
261 int gw_count, ret;
262 str uri_user;
263 str caller_uri;
264 str request_uri;
265 unsigned int gw_indexes[MAX_NO_OF_GWS];
266 struct gw_info *gws;
267 void *rec = NULL;
268 void *st = NULL;
269
270 ret = rpc->scan(c, "dS*SS", &lcr_id, &uri_user, &caller_uri, &request_uri);
271 if(ret == -1) {
272 rpc->fault(c, 400, "parameter error; if using cli, remember to prefix "
273 "numeric uri_user param value with 's:'");
274 return;
275 }
276
277 if(ret < 4)
278 request_uri.len = 0;
279 if(ret < 3)
280 caller_uri.len = 0;
281
282 gw_count = load_gws_dummy(
283 lcr_id, &uri_user, &caller_uri, &request_uri, &(gw_indexes[0]));
284
285 if(gw_count < 0) {
286 rpc->fault(c, 400, "load_gws excution error (see syslog)");
287 return;
288 }
289
290 gws = gw_pt[lcr_id];
291 for(j = 0; j < gw_count; j++) {
292 if (rec==NULL) {
293 if(rpc->add(c, "[", &rec) < 0)
294 return;
295 }
296 if(rpc->array_add(rec, "{", &st) < 0)
297 return;
298 i = gw_indexes[j];
299 dump_gw(rpc, st, &gws[i], i, lcr_id);
300 }
301
302 return;
303 }
304
305 /* clang-format off */
306 rpc_export_t lcr_rpc[] = {
307 {"lcr.reload", reload, reload_doc, 0},
308 {"lcr.dump_gws", dump_gws, dump_gws_doc, 0},
309 {"lcr.dump_rules", dump_rules, dump_rules_doc, 0},
310 {"lcr.defunct_gw", defunct_gw, defunct_gw_doc, 0},
311 {"lcr.load_gws", load_gws, load_gws_doc, 0},
312 {0, 0, 0, 0}
313 };
314 /* clang-format on */
315