utils/utils.c

Go to the documentation of this file.
00001 /*
00002  * utils Module
00003  *
00004  * Copyright (C) 2008 Juha Heinanen
00005  * Copyright (C) 2009 1&1 Internet AG
00006  *
00007  * This file is part of Kamailio, a free SIP server.
00008  *
00009  * Kamailio is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version
00013  *
00014  * Kamailio is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License 
00020  * along with this program; if not, write to the Free Software 
00021  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022  *
00023  * History:
00024  * -------
00025  * 2008-11-24: Introduced utils module and its first function: http_query.
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 /* module parameters */
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 /* lock for configuration access */
00056 static gen_lock_t *conf_lock = NULL;
00057 
00058 
00059 /* FIFO interface functions */
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 /* Module management function prototypes */
00067 static int mod_init(void);
00068 static void destroy(void);
00069 
00070 
00071 /* Module parameter variables */
00072 int http_query_timeout = 4;
00073 
00074 
00075 /* Fixup functions to be defined later */
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 /* forward function */
00080 int utils_forward(struct sip_msg *msg, int id, int proto);
00081 
00082 /* Exported functions */
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 /* Exported parameters */
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 /* Module interface */
00107 struct module_exports exports = {
00108     "utils",
00109     DEFAULT_DLFLAGS, /* dlopen flags */
00110     cmds,      /* Exported functions */
00111     params,    /* Exported parameters */
00112     0,         /* exported statistics */
00113     mi_cmds,   /* exported MI functions */
00114     0,         /* exported pseudo-variables */
00115     0,         /* extra processes */
00116     mod_init,  /* module initialization function */
00117     0,         /* response function*/
00118     destroy,   /* destroy function */
00119     0          /* per-child init function */
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    /* use id 0 for pre script callback */
00142    utils_forward(msg, 0, PROTO_UDP);
00143 
00144    /* always return 1 so that routing skript is called for msg */
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 /* Module initialization function */
00160 static int mod_init(void)
00161 {
00162    /* Initialize curl */
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    /* read module parameters and update configuration structure */
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       /* register callback for id 0 */
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    /* Cleanup curl */
00213    curl_global_cleanup();
00214    /* Cleanup forward */
00215    conf_destroy();
00216    destroy_shmlock();
00217 }
00218 
00219 
00220 /* Fixup functions */
00221 
00222 /*
00223  * Fix http_query params: url (string that may contain pvars) and
00224  * result (writable pvar).
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  * Free http_query params.
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  * \brief checks precondition, switch, filter and forwards msg if necessary
00270  * \param msg the message to be forwarded
00271  * \param id use configuration with this ID when checking switch, filter, proxy.
00272  * \param proto protocol to be used. Should be PROTO_UDP.
00273  *  \return 0 on success, -1 otherwise
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    // critical section start:
00288    // avoids dirty reads when updating configuration.
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    // critical section end
00315    lock_release(conf_lock);
00316    pkg_free(to);
00317 
00318    return ret;
00319 }
00320 
00321 
00322 /* FIFO functions */
00323 
00324 /*!
00325  * \brief fifo command for listing configuration
00326  * \return pointer to the mi_root on success, 0 otherwise
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    // critical section start:
00340    // avoids dirty reads when updating configuration.
00341    lock_get(conf_lock);
00342 
00343    conf_show(ret);
00344 
00345    // critical section end
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  * \brief fifo command for configuring switch
00358  * \return pointer to the mi_root on success, 0 otherwise
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    // critical section start:
00370    // avoids dirty reads when updating configuration.
00371    lock_get(conf_lock);
00372 
00373    result = conf_parse_switch(node->value.s);
00374 
00375    // critical section end
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  * \brief fifo command for configuring filter
00388  * \return pointer to the mi_root on success, 0 otherwise
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    // critical section start:
00400    //   avoids dirty reads when updating configuration.
00401    lock_get(conf_lock);
00402 
00403    result = conf_parse_filter(node->value.s);
00404 
00405    // critical section end
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  * \brief fifo command for configuring proxy
00418  * \return pointer to the mi_root on success, 0 otherwise
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    // critical section start:
00430    //   avoids dirty reads when updating configuration.
00431    lock_get(conf_lock);
00432 
00433    result = conf_parse_proxy(node->value.s);
00434 
00435    // critical section end
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 }

Generated on Thu May 24 22:00:35 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6