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
00029
00030 #include <curl/curl.h>
00031
00032 #include "../../mod_fix.h"
00033 #include "../../sr_module.h"
00034 #include "../../ut.h"
00035 #include "../../forward.h"
00036 #include "../../resolve.h"
00037 #include "../../locking.h"
00038 #include "../../script_cb.h"
00039 #include "../../mem/shm_mem.h"
00040
00041 #include "functions.h"
00042 #include "conf.h"
00043
00044
00045 MODULE_VERSION
00046
00047
00048
00049 static int forward_active = 0;
00050 static int mp_max_id = 0;
00051 static char* mp_switch = "";
00052 static char* mp_filter = "";
00053 static char* mp_proxy = "";
00054
00055
00056 static gen_lock_t *conf_lock = NULL;
00057
00058
00059
00060 static struct mi_root* forward_fifo_list(struct mi_root* cmd_tree, void *param);
00061 static struct mi_root* forward_fifo_switch(struct mi_root* cmd_tree, void* param);
00062 static struct mi_root* forward_fifo_filter(struct mi_root* cmd_tree, void* param);
00063 static struct mi_root* forward_fifo_proxy(struct mi_root* cmd_tree, void* param);
00064
00065
00066
00067 static int mod_init(void);
00068 static void destroy(void);
00069
00070
00071
00072 int http_query_timeout = 4;
00073
00074
00075
00076 static int fixup_http_query(void** param, int param_no);
00077 static int fixup_free_http_query(void** param, int param_no);
00078
00079
00080 int utils_forward(struct sip_msg *msg, int id, int proto);
00081
00082
00083 static cmd_export_t cmds[] = {
00084 {"http_query", (cmd_function)http_query, 2, fixup_http_query,
00085 fixup_free_http_query,
00086 REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE},
00087 {0, 0, 0, 0, 0, 0}
00088 };
00089
00090
00091
00092 static param_export_t params[] = {
00093 {"http_query_timeout", INT_PARAM, &http_query_timeout},
00094 {"forward_active", INT_PARAM, &forward_active},
00095 {0, 0, 0}
00096 };
00097
00098 static mi_export_t mi_cmds[] = {
00099 { "forward_list", forward_fifo_list, MI_NO_INPUT_FLAG, 0, 0 },
00100 { "forward_switch", forward_fifo_switch, 0, 0, 0 },
00101 { "forward_filter", forward_fifo_filter, 0, 0, 0 },
00102 { "forward_proxy", forward_fifo_proxy, 0, 0, 0 },
00103 { 0, 0, 0, 0, 0}
00104 };
00105
00106
00107 struct module_exports exports = {
00108 "utils",
00109 DEFAULT_DLFLAGS,
00110 cmds,
00111 params,
00112 0,
00113 mi_cmds,
00114 0,
00115 0,
00116 mod_init,
00117 0,
00118 destroy,
00119 0
00120 };
00121
00122
00123 static int init_shmlock(void)
00124 {
00125 conf_lock = lock_alloc();
00126 if (conf_lock == NULL) {
00127 LM_CRIT("cannot allocate memory for lock.\n");
00128 return -1;
00129 }
00130 if (lock_init(conf_lock) == 0) {
00131 LM_CRIT("cannot initialize lock.\n");
00132 return -1;
00133 }
00134
00135 return 0;
00136 }
00137
00138
00139 static int pre_script_filter(struct sip_msg *msg, void *unused)
00140 {
00141
00142 utils_forward(msg, 0, PROTO_UDP);
00143
00144
00145 return 1;
00146 }
00147
00148
00149 static void destroy_shmlock(void)
00150 {
00151 if (conf_lock) {
00152 lock_destroy(conf_lock);
00153 lock_dealloc((void *)conf_lock);
00154 conf_lock = NULL;
00155 }
00156 }
00157
00158
00159
00160 static int mod_init(void)
00161 {
00162
00163 if (curl_global_init(CURL_GLOBAL_ALL)) {
00164 LM_ERR("curl_global_init failed\n");
00165 return -1;
00166 }
00167
00168
00169 if (init_shmlock() != 0) {
00170 LM_CRIT("cannot initialize shmlock.\n");
00171 return -1;
00172 }
00173
00174 if (conf_init(mp_max_id) < 0) {
00175 LM_CRIT("cannot initialize configuration.\n");
00176 return -1;
00177 }
00178
00179
00180 if (conf_parse_proxy(mp_proxy) < 0) {
00181 LM_CRIT("cannot parse proxy module parameter.\n");
00182 return -1;
00183 }
00184 if (conf_parse_filter(mp_filter) < 0) {
00185 LM_CRIT("cannot parse filter module parameter.\n");
00186 return -1;
00187 }
00188 if (conf_parse_switch(mp_switch) < 0) {
00189 LM_CRIT("cannot parse switch module parameter.\n");
00190 return -1;
00191 }
00192
00193 if (forward_active == 1) {
00194
00195 if (register_script_cb(pre_script_filter, PRE_SCRIPT_CB|REQ_TYPE_CB, 0) < 0) {
00196 LM_CRIT("cannot register script callback for requests.\n");
00197 return -1;
00198 }
00199 if (register_script_cb(pre_script_filter, PRE_SCRIPT_CB|RPL_TYPE_CB, 0) < 0) {
00200 LM_CRIT("cannot register script callback for replies.\n");
00201 return -1;
00202 }
00203 } else {
00204 LM_INFO("forward functionality disabled");
00205 }
00206 return 0;
00207 }
00208
00209
00210 static void destroy(void)
00211 {
00212
00213 curl_global_cleanup();
00214
00215 conf_destroy();
00216 destroy_shmlock();
00217 }
00218
00219
00220
00221
00222
00223
00224
00225
00226 static int fixup_http_query(void** param, int param_no)
00227 {
00228 if (param_no == 1) {
00229 return fixup_spve_null(param, 1);
00230 }
00231
00232 if (param_no == 2) {
00233 if (fixup_pvar(param) != 0) {
00234 LM_ERR("failed to fixup result pvar\n");
00235 return -1;
00236 }
00237 if (((pv_spec_t *)(*param))->setf == NULL) {
00238 LM_ERR("result pvar is not writeble\n");
00239 return -1;
00240 }
00241 LM_INFO("leaving fixup_http_query\n");
00242 return 0;
00243 }
00244
00245 LM_ERR("invalid parameter number <%d>\n", param_no);
00246 return -1;
00247 }
00248
00249
00250
00251
00252 static int fixup_free_http_query(void** param, int param_no)
00253 {
00254 if (param_no == 1) {
00255 LM_WARN("free function has not been defined for spve\n");
00256 return 0;
00257 }
00258
00259 if (param_no == 2) {
00260 return fixup_free_pvar_null(param, 1);
00261 }
00262
00263 LM_ERR("invalid parameter number <%d>\n", param_no);
00264 return -1;
00265 }
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275 int utils_forward(struct sip_msg *msg, int id, int proto)
00276 {
00277 int ret = -1;
00278 union sockaddr_union* to = NULL;
00279 struct socket_info *send_sock = NULL;
00280
00281 to = (union sockaddr_union*)pkg_malloc(sizeof(union sockaddr_union));
00282 if (to == NULL) {
00283 PKG_MEM_ERROR;
00284 return -1;
00285 }
00286
00287
00288
00289 lock_get(conf_lock);
00290
00291 struct proxy_l *proxy = conf_needs_forward(msg, id);
00292
00293 if (proxy != NULL) {
00294 hostent2su(to, &proxy->host, proxy->addr_idx, (proxy->port)?proxy->port:SIP_PORT);
00295 do {
00296 send_sock=get_send_socket(msg, to, proto);
00297
00298 if (send_sock==0) {
00299 LM_ERR("cannot forward to af %d, "
00300 "proto %d no corresponding listening socket\n", to->s.sa_family, proto);
00301 continue;
00302 }
00303 LM_DBG("Sending:\n%.*s.\n", (int)msg->len,msg->buf);
00304
00305 if (msg_send(send_sock, proto, to, 0, msg->buf,msg->len)<0){
00306 LM_ERR("Error sending message!\n");
00307 continue;
00308 }
00309 ret = 0;
00310 break;
00311 } while( get_next_su( proxy, to, 0) == 0 );
00312 }
00313
00314
00315 lock_release(conf_lock);
00316 pkg_free(to);
00317
00318 return ret;
00319 }
00320
00321
00322
00323
00324
00325
00326
00327
00328 static struct mi_root* forward_fifo_list(struct mi_root* cmd_tree, void *param)
00329 {
00330 struct mi_node *node = NULL;
00331 struct mi_root * ret = init_mi_tree(200, MI_OK_S, MI_OK_LEN);
00332 if(ret == NULL)
00333 return 0;
00334
00335 node = addf_mi_node_child( &ret->node, 0, 0, 0, "Printing forwarding information:");
00336 if(node == NULL)
00337 goto error;
00338
00339
00340
00341 lock_get(conf_lock);
00342
00343 conf_show(ret);
00344
00345
00346 lock_release(conf_lock);
00347
00348 return ret;
00349
00350 error:
00351 free_mi_tree(ret);
00352 return 0;
00353 }
00354
00355
00356
00357
00358
00359
00360 static struct mi_root* forward_fifo_switch(struct mi_root* cmd_tree, void* param)
00361 {
00362 struct mi_node *node = NULL;
00363 int result;
00364
00365 node = cmd_tree->node.kids;
00366 if (node==NULL || node->next!=NULL || node->value.s==NULL)
00367 return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00368
00369
00370
00371 lock_get(conf_lock);
00372
00373 result = conf_parse_switch(node->value.s);
00374
00375
00376 lock_release(conf_lock);
00377
00378 if (result < 0) {
00379 LM_ERR("cannot parse parameter\n");
00380 return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
00381 }
00382 return init_mi_tree(200, MI_OK_S, MI_OK_LEN);
00383 }
00384
00385
00386
00387
00388
00389
00390 static struct mi_root* forward_fifo_filter(struct mi_root* cmd_tree, void* param)
00391 {
00392 struct mi_node *node = NULL;
00393 int result;
00394
00395 node = cmd_tree->node.kids;
00396 if (node==NULL || node->next!=NULL || node->value.s==NULL)
00397 return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00398
00399
00400
00401 lock_get(conf_lock);
00402
00403 result = conf_parse_filter(node->value.s);
00404
00405
00406 lock_release(conf_lock);
00407
00408 if (result < 0) {
00409 LM_ERR("cannot parse parameter\n");
00410 return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
00411 }
00412 return init_mi_tree(200, MI_OK_S, MI_OK_LEN);
00413 }
00414
00415
00416
00417
00418
00419
00420 static struct mi_root* forward_fifo_proxy(struct mi_root* cmd_tree, void* param)
00421 {
00422 struct mi_node *node = NULL;
00423 int result;
00424
00425 node = cmd_tree->node.kids;
00426 if (node==NULL || node->next!=NULL || node->value.s==NULL)
00427 return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00428
00429
00430
00431 lock_get(conf_lock);
00432
00433 result = conf_parse_proxy(node->value.s);
00434
00435
00436 lock_release(conf_lock);
00437
00438 if (result < 0) {
00439 LM_ERR("cannot parse parameter\n");
00440 return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
00441 }
00442 return init_mi_tree(200, MI_OK_S, MI_OK_LEN);
00443 }