00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00041 #include <curl/curl.h>
00042
00043 #include "../../mod_fix.h"
00044 #include "../../sr_module.h"
00045 #include "../../ut.h"
00046 #include "../../forward.h"
00047 #include "../../resolve.h"
00048 #include "../../locking.h"
00049 #include "../../script_cb.h"
00050 #include "../../mem/shm_mem.h"
00051 #include "../../lib/srdb1/db.h"
00052
00053 #include "functions.h"
00054 #include "conf.h"
00055 #include "xcap_auth.h"
00056
00057
00058 MODULE_VERSION
00059
00060 #define XCAP_TABLE_VERSION 4
00061
00062
00063 int http_query_timeout = 4;
00064 static int forward_active = 0;
00065 static int mp_max_id = 0;
00066 static char* mp_switch = "";
00067 static char* mp_filter = "";
00068 static char* mp_proxy = "";
00069 str xcap_table= str_init("xcap");
00070 str pres_db_url = {0, 0};
00071
00072
00073 static gen_lock_t *conf_lock = NULL;
00074
00075
00076 static struct mi_root* forward_fifo_list(struct mi_root* cmd_tree, void *param);
00077 static struct mi_root* forward_fifo_switch(struct mi_root* cmd_tree, void* param);
00078 static struct mi_root* forward_fifo_filter(struct mi_root* cmd_tree, void* param);
00079 static struct mi_root* forward_fifo_proxy(struct mi_root* cmd_tree, void* param);
00080
00081
00082 db1_con_t *pres_dbh = NULL;
00083 db_func_t pres_dbf;
00084
00085
00086 static int mod_init(void);
00087 static int child_init(int);
00088 static void destroy(void);
00089
00090
00091 static int fixup_http_query(void** param, int param_no);
00092 static int fixup_free_http_query(void** param, int param_no);
00093
00094
00095 int utils_forward(struct sip_msg *msg, int id, int proto);
00096
00097
00098 static cmd_export_t cmds[] = {
00099 {"http_query", (cmd_function)http_query, 2, fixup_http_query,
00100 fixup_free_http_query,
00101 REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE},
00102 {"xcap_auth_status", (cmd_function)xcap_auth_status, 2, fixup_pvar_pvar,
00103 fixup_free_pvar_pvar, REQUEST_ROUTE},
00104 {0, 0, 0, 0, 0, 0}
00105 };
00106
00107
00108
00109 static param_export_t params[] = {
00110 {"pres_db_url", STR_PARAM, &pres_db_url.s},
00111 {"xcap_table", STR_PARAM, &xcap_table.s},
00112 {"http_query_timeout", INT_PARAM, &http_query_timeout},
00113 {"forward_active", INT_PARAM, &forward_active},
00114 {0, 0, 0}
00115 };
00116
00117 static mi_export_t mi_cmds[] = {
00118 { "forward_list", forward_fifo_list, MI_NO_INPUT_FLAG, 0, 0 },
00119 { "forward_switch", forward_fifo_switch, 0, 0, 0 },
00120 { "forward_filter", forward_fifo_filter, 0, 0, 0 },
00121 { "forward_proxy", forward_fifo_proxy, 0, 0, 0 },
00122 { 0, 0, 0, 0, 0}
00123 };
00124
00125
00126 struct module_exports exports = {
00127 "utils",
00128 DEFAULT_DLFLAGS,
00129 cmds,
00130 params,
00131 0,
00132 mi_cmds,
00133 0,
00134 0,
00135 mod_init,
00136 0,
00137 destroy,
00138 child_init
00139 };
00140
00141
00142 static int init_shmlock(void)
00143 {
00144 conf_lock = lock_alloc();
00145 if (conf_lock == NULL) {
00146 LM_CRIT("cannot allocate memory for lock.\n");
00147 return -1;
00148 }
00149 if (lock_init(conf_lock) == 0) {
00150 LM_CRIT("cannot initialize lock.\n");
00151 return -1;
00152 }
00153
00154 return 0;
00155 }
00156
00157
00158 static int pre_script_filter(struct sip_msg *msg, unsigned int flags, void *unused)
00159 {
00160
00161 utils_forward(msg, 0, PROTO_UDP);
00162
00163
00164 return 1;
00165 }
00166
00167
00168 static void destroy_shmlock(void)
00169 {
00170 if (conf_lock) {
00171 lock_destroy(conf_lock);
00172 lock_dealloc((void *)conf_lock);
00173 conf_lock = NULL;
00174 }
00175 }
00176
00177
00178 static void pres_db_close(void) {
00179 if (pres_dbh) {
00180 pres_dbf.close(pres_dbh);
00181 pres_dbh = NULL;
00182 }
00183 }
00184
00185 static int pres_db_init(void) {
00186 if (!pres_db_url.s || !pres_db_url.len) {
00187 LM_INFO("xcap_auth_status function is disabled\n");
00188 return 0;
00189 }
00190 if (db_bind_mod(&pres_db_url, &pres_dbf) < 0) {
00191 LM_ERR("can't bind database module\n");
00192 return -1;
00193 }
00194 if ((pres_dbh = pres_dbf.init(&pres_db_url)) == NULL) {
00195 LM_ERR("can't connect to database\n");
00196 return -1;
00197 }
00198 if (db_check_table_version(&pres_dbf, pres_dbh, &xcap_table,
00199 XCAP_TABLE_VERSION) < 0) {
00200 LM_ERR("during table version check\n");
00201 pres_db_close();
00202 return -1;
00203 }
00204 pres_db_close();
00205 return 0;
00206 }
00207
00208 static int pres_db_open(void) {
00209 if (!pres_db_url.s || !pres_db_url.len) {
00210 return 0;
00211 }
00212 if (pres_dbh) {
00213 pres_dbf.close(pres_dbh);
00214 }
00215 if ((pres_dbh = pres_dbf.init(&pres_db_url)) == NULL) {
00216 LM_ERR("can't connect to database\n");
00217 return -1;
00218 }
00219 if (pres_dbf.use_table(pres_dbh, &xcap_table) < 0) {
00220 LM_ERR("in use_table: %.*s\n", xcap_table.len, xcap_table.s);
00221 return -1;
00222 }
00223 return 0;
00224 }
00225
00226
00227
00228 static int mod_init(void)
00229 {
00230 if(register_mi_mod(exports.name, mi_cmds)!=0)
00231 {
00232 LM_ERR("failed to register MI commands\n");
00233 return -1;
00234 }
00235
00236
00237 if (curl_global_init(CURL_GLOBAL_ALL)) {
00238 LM_ERR("curl_global_init failed\n");
00239 return -1;
00240 }
00241
00242
00243 if (init_shmlock() != 0) {
00244 LM_CRIT("cannot initialize shmlock.\n");
00245 return -1;
00246 }
00247
00248 if (conf_init(mp_max_id) < 0) {
00249 LM_CRIT("cannot initialize configuration.\n");
00250 return -1;
00251 }
00252
00253
00254 if (conf_parse_proxy(mp_proxy) < 0) {
00255 LM_CRIT("cannot parse proxy module parameter.\n");
00256 return -1;
00257 }
00258 if (conf_parse_filter(mp_filter) < 0) {
00259 LM_CRIT("cannot parse filter module parameter.\n");
00260 return -1;
00261 }
00262 if (conf_parse_switch(mp_switch) < 0) {
00263 LM_CRIT("cannot parse switch module parameter.\n");
00264 return -1;
00265 }
00266
00267 if (forward_active == 1) {
00268
00269 if (register_script_cb(pre_script_filter, PRE_SCRIPT_CB|ONREPLY_CB, 0) < 0) {
00270 LM_CRIT("cannot register script callback for requests.\n");
00271 return -1;
00272 }
00273 if (register_script_cb(pre_script_filter, PRE_SCRIPT_CB|ONREPLY_CB, 0) < 0) {
00274 LM_CRIT("cannot register script callback for replies.\n");
00275 return -1;
00276 }
00277 } else {
00278 LM_INFO("forward functionality disabled");
00279 }
00280
00281
00282 pres_db_url.len = pres_db_url.s ? strlen(pres_db_url.s) : 0;
00283 LM_DBG("pres_db_url=%s/%d/%p\n", ZSW(pres_db_url.s), pres_db_url.len,
00284 pres_db_url.s);
00285 xcap_table.len = xcap_table.s ? strlen(xcap_table.s) : 0;
00286
00287 if(pres_db_init() < 0) {
00288 return -1;
00289 }
00290
00291 return 0;
00292 }
00293
00294
00295
00296 static int child_init(int rank)
00297 {
00298 if (rank==PROC_INIT || rank==PROC_MAIN || rank==PROC_TCP_MAIN)
00299 return 0;
00300
00301 return pres_db_open();
00302 }
00303
00304 static void destroy(void)
00305 {
00306
00307 curl_global_cleanup();
00308
00309 conf_destroy();
00310 destroy_shmlock();
00311
00312 pres_db_close();
00313 }
00314
00315
00316
00317
00318
00319
00320
00321
00322 static int fixup_http_query(void** param, int param_no)
00323 {
00324 if (param_no == 1) {
00325 return fixup_spve_null(param, 1);
00326 }
00327
00328 if (param_no == 2) {
00329 if (fixup_pvar_null(param, 1) != 0) {
00330 LM_ERR("failed to fixup result pvar\n");
00331 return -1;
00332 }
00333 if (((pv_spec_t *)(*param))->setf == NULL) {
00334 LM_ERR("result pvar is not writeble\n");
00335 return -1;
00336 }
00337 return 0;
00338 }
00339
00340 LM_ERR("invalid parameter number <%d>\n", param_no);
00341 return -1;
00342 }
00343
00344
00345
00346
00347 static int fixup_free_http_query(void** param, int param_no)
00348 {
00349 if (param_no == 1) {
00350 LM_WARN("free function has not been defined for spve\n");
00351 return 0;
00352 }
00353
00354 if (param_no == 2) {
00355 return fixup_free_pvar_null(param, 1);
00356 }
00357
00358 LM_ERR("invalid parameter number <%d>\n", param_no);
00359 return -1;
00360 }
00361
00362
00370 int utils_forward(struct sip_msg *msg, int id, int proto)
00371 {
00372 int ret = -1;
00373 struct dest_info dst;
00374
00375 init_dest_info(&dst);
00376 dst.proto = proto;
00377
00378
00379
00380 lock_get(conf_lock);
00381
00382 struct proxy_l *proxy = conf_needs_forward(msg, id);
00383
00384 if (proxy != NULL) {
00385 proxy2su(&dst.to, proxy);
00386 if (forward_request(msg, NULL, 0, &dst) < 0){
00387 LM_ERR("could not forward message\n");
00388 }
00389 ret = 0;
00390 }
00391
00392
00393 lock_release(conf_lock);
00394
00395 return ret;
00396 }
00397
00398
00399
00400
00405 static struct mi_root* forward_fifo_list(struct mi_root* cmd_tree, void *param)
00406 {
00407 struct mi_node *node = NULL;
00408 struct mi_root * ret = init_mi_tree(200, MI_OK_S, MI_OK_LEN);
00409 if(ret == NULL)
00410 return 0;
00411
00412 node = addf_mi_node_child( &ret->node, 0, 0, 0, "Printing forwarding information:");
00413 if(node == NULL)
00414 goto error;
00415
00416
00417
00418 lock_get(conf_lock);
00419
00420 conf_show(ret);
00421
00422
00423 lock_release(conf_lock);
00424
00425 return ret;
00426
00427 error:
00428 free_mi_tree(ret);
00429 return 0;
00430 }
00431
00432
00437 static struct mi_root* forward_fifo_switch(struct mi_root* cmd_tree, void* param)
00438 {
00439 struct mi_node *node = NULL;
00440 int result;
00441
00442 node = cmd_tree->node.kids;
00443 if (node==NULL || node->next!=NULL || node->value.s==NULL)
00444 return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00445
00446
00447
00448 lock_get(conf_lock);
00449
00450 result = conf_parse_switch(node->value.s);
00451
00452
00453 lock_release(conf_lock);
00454
00455 if (result < 0) {
00456 LM_ERR("cannot parse parameter\n");
00457 return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
00458 }
00459 return init_mi_tree(200, MI_OK_S, MI_OK_LEN);
00460 }
00461
00462
00467 static struct mi_root* forward_fifo_filter(struct mi_root* cmd_tree, void* param)
00468 {
00469 struct mi_node *node = NULL;
00470 int result;
00471
00472 node = cmd_tree->node.kids;
00473 if (node==NULL || node->next!=NULL || node->value.s==NULL)
00474 return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00475
00476
00477
00478 lock_get(conf_lock);
00479
00480 result = conf_parse_filter(node->value.s);
00481
00482
00483 lock_release(conf_lock);
00484
00485 if (result < 0) {
00486 LM_ERR("cannot parse parameter\n");
00487 return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
00488 }
00489 return init_mi_tree(200, MI_OK_S, MI_OK_LEN);
00490 }
00491
00492
00497 static struct mi_root* forward_fifo_proxy(struct mi_root* cmd_tree, void* param)
00498 {
00499 struct mi_node *node = NULL;
00500 int result;
00501
00502 node = cmd_tree->node.kids;
00503 if (node==NULL || node->next!=NULL || node->value.s==NULL)
00504 return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00505
00506
00507
00508 lock_get(conf_lock);
00509
00510 result = conf_parse_proxy(node->value.s);
00511
00512
00513 lock_release(conf_lock);
00514
00515 if (result < 0) {
00516 LM_ERR("cannot parse parameter\n");
00517 return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
00518 }
00519 return init_mi_tree(200, MI_OK_S, MI_OK_LEN);
00520 }