123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441 |
- /*
- * $Id$
- *
- * Copyright (C) 2008-2009 1&1 Internet AG
- * Copyright (C) 2001-2003 FhG Fokus
- *
- * This file is part of SIP-router, a free SIP server.
- *
- * SIP-router is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version
- *
- * SIP-router is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
- /*!
- * \file
- * \brief Module with several utiltity functions related to SIP messages handling
- * \ingroup siputils
- * - Module \ref siputils
- */
- /*!
- * \defgroup siputils SIPUTILS :: Various SIP message handling functions
- *
- * \note A Kamailio module (modules_k)
- *
- This module implement various functions and checks related to
- SIP message handling and URI handling.
- It offers some functions related to handle ringing. In a
- parallel forking scenario you get several 183s with SDP. You
- don't want that your customers hear more than one ringtone or
- answer machine in parallel on the phone. So its necessary to
- drop the 183 in this cases and send a 180 instead.
- This module provides a function to answer OPTIONS requests
- which are directed to the server itself. This means an OPTIONS
- request which has the address of the server in the request
- URI, and no username in the URI. The request will be answered
- with a 200 OK which the capabilities of the server.
- To answer OPTIONS request directed to your server is the
- easiest way for is-alive-tests on the SIP (application) layer
- from remote (similar to ICMP echo requests, also known as
- "ping", on the network layer).
- */
- #include <assert.h>
- #include "../../sr_module.h"
- #include "../../mem/mem.h"
- #include "../../dprint.h"
- #include "../../script_cb.h"
- #include "../../locking.h"
- #include "../../ut.h"
- #include "../../mod_fix.h"
- #include "../../error.h"
- #include "../../parser/parse_option_tags.h"
- #include "ring.h"
- #include "options.h"
- #include "checks.h"
- #include "rpid.h"
- #include "siputils.h"
- #include "utils.h"
- #include "contact_ops.h"
- #include "sipops.h"
- #include "config.h"
- MODULE_VERSION
- /* rpid handling defs */
- #define DEF_RPID_PREFIX ""
- #define DEF_RPID_SUFFIX ";party=calling;id-type=subscriber;screen=yes"
- #define DEF_RPID_AVP "$avp(s:rpid)"
- /*! Default Remote-Party-ID prefix */
- str rpid_prefix = {DEF_RPID_PREFIX, sizeof(DEF_RPID_PREFIX) - 1};
- /*! Default Remote-Party-IDD suffix */
- str rpid_suffix = {DEF_RPID_SUFFIX, sizeof(DEF_RPID_SUFFIX) - 1};
- /*! Definition of AVP containing rpid value */
- char* rpid_avp_param = DEF_RPID_AVP;
- gen_lock_t *ring_lock = NULL;
- unsigned int ring_timeout = 0;
- /* for options functionality */
- str opt_accept = str_init(ACPT_DEF);
- str opt_accept_enc = str_init(ACPT_ENC_DEF);
- str opt_accept_lang = str_init(ACPT_LAN_DEF);
- str opt_supported = str_init(SUPT_DEF);
- /** SL API structure */
- sl_api_t opt_slb;
- static int mod_init(void);
- static void mod_destroy(void);
- /* Fixup functions to be defined later */
- static int fixup_set_uri(void** param, int param_no);
- static int fixup_free_set_uri(void** param, int param_no);
- static int fixup_tel2sip(void** param, int param_no);
- static int fixup_get_uri_param(void** param, int param_no);
- static int free_fixup_get_uri_param(void** param, int param_no);
- static int fixup_option(void** param, int param_no);
- char *contact_flds_separator = DEFAULT_SEPARATOR;
- static cmd_export_t cmds[]={
- {"ring_insert_callid", (cmd_function)ring_insert_callid, 0, ring_fixup,
- 0, REQUEST_ROUTE|FAILURE_ROUTE},
- {"options_reply", (cmd_function)opt_reply, 0, 0,
- 0, REQUEST_ROUTE},
- {"is_user", (cmd_function)is_user, 1, fixup_str_null,
- 0, REQUEST_ROUTE|LOCAL_ROUTE},
- {"has_totag", (cmd_function)has_totag, 0, 0,
- 0, ANY_ROUTE},
- {"uri_param", (cmd_function)uri_param_1, 1, fixup_str_null,
- 0, REQUEST_ROUTE|LOCAL_ROUTE},
- {"uri_param", (cmd_function)uri_param_2, 2, fixup_str_str,
- 0, REQUEST_ROUTE|LOCAL_ROUTE},
- {"add_uri_param", (cmd_function)add_uri_param, 1, fixup_str_null,
- 0, REQUEST_ROUTE},
- {"get_uri_param", (cmd_function)get_uri_param, 2, fixup_get_uri_param,
- free_fixup_get_uri_param, REQUEST_ROUTE|LOCAL_ROUTE},
- {"tel2sip", (cmd_function)tel2sip, 3, fixup_tel2sip, 0,
- REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONREPLY_ROUTE},
- {"is_e164", (cmd_function)is_e164, 1, fixup_pvar_null,
- fixup_free_pvar_null, REQUEST_ROUTE|FAILURE_ROUTE|LOCAL_ROUTE},
- {"is_uri_user_e164", (cmd_function)w_is_uri_user_e164, 1, fixup_pvar_null,
- fixup_free_pvar_null, ANY_ROUTE},
- {"encode_contact", (cmd_function)encode_contact, 2, 0,
- 0, REQUEST_ROUTE|ONREPLY_ROUTE},
- {"decode_contact", (cmd_function)decode_contact, 0, 0,
- 0, REQUEST_ROUTE},
- {"decode_contact_header", (cmd_function)decode_contact_header, 0, 0,
- 0,REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE},
- {"cmp_uri", (cmd_function)w_cmp_uri, 2, fixup_spve_spve,
- 0, ANY_ROUTE},
- {"cmp_aor", (cmd_function)w_cmp_aor, 2, fixup_spve_spve,
- 0, ANY_ROUTE},
- {"is_rpid_user_e164", (cmd_function)is_rpid_user_e164, 0, 0,
- 0, REQUEST_ROUTE},
- {"append_rpid_hf", (cmd_function)append_rpid_hf, 0, 0,
- 0, REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE},
- {"append_rpid_hf", (cmd_function)append_rpid_hf_p, 2, fixup_str_str,
- 0, REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE},
- {"set_uri_user", (cmd_function)set_uri_user, 2, fixup_set_uri,
- fixup_free_set_uri, ANY_ROUTE},
- {"set_uri_host", (cmd_function)set_uri_host, 2, fixup_set_uri,
- fixup_free_set_uri, ANY_ROUTE},
- {"bind_siputils", (cmd_function)bind_siputils, 1, 0,
- 0, 0},
- {"is_request", (cmd_function)w_is_request, 0, 0,
- 0, ANY_ROUTE},
- {"is_reply", (cmd_function)w_is_reply, 0, 0,
- 0, ANY_ROUTE},
- {"is_gruu", (cmd_function)w_is_gruu, 0, 0,
- 0, ANY_ROUTE},
- {"is_gruu", (cmd_function)w_is_gruu, 1, fixup_spve_null,
- 0, ANY_ROUTE},
- {"is_supported", (cmd_function)w_is_supported, 1, fixup_option,
- 0, ANY_ROUTE},
- {"is_first_hop", (cmd_function)w_is_first_hop, 0, 0,
- 0, ANY_ROUTE},
- {0,0,0,0,0,0}
- };
- static param_export_t params[] = {
- {"ring_timeout", INT_PARAM, &default_siputils_cfg.ring_timeout},
- {"options_accept", PARAM_STR, &opt_accept},
- {"options_accept_encoding", PARAM_STR, &opt_accept_enc},
- {"options_accept_language", PARAM_STR, &opt_accept_lang},
- {"options_support", PARAM_STR, &opt_supported},
- {"contact_flds_separator", PARAM_STRING, &contact_flds_separator},
- {"rpid_prefix", PARAM_STR, &rpid_prefix },
- {"rpid_suffix", PARAM_STR, &rpid_suffix },
- {"rpid_avp", PARAM_STRING, &rpid_avp_param },
- {0, 0, 0}
- };
- struct module_exports exports= {
- "siputils",
- DEFAULT_DLFLAGS, /* dlopen flags */
- cmds, /* Exported functions */
- params, /* param exports */
- 0, /* exported statistics */
- 0, /* exported MI functions */
- 0, /* exported pseudo-variables */
- 0, /* extra processes */
- mod_init, /* initialization function */
- 0, /* Response function */
- mod_destroy, /* Destroy function */
- 0, /* Child init function */
- };
- static int mod_init(void)
- {
- if(default_siputils_cfg.ring_timeout > 0) {
- ring_init_hashtable();
- ring_lock = lock_alloc();
- assert(ring_lock);
- if (lock_init(ring_lock) == 0) {
- LM_CRIT("cannot initialize lock.\n");
- return -1;
- }
- if (register_script_cb(ring_filter, PRE_SCRIPT_CB|ONREPLY_CB, 0) != 0) {
- LM_ERR("could not insert callback");
- return -1;
- }
- }
- /* bind the SL API */
- if (sl_load_api(&opt_slb)!=0) {
- LM_ERR("cannot bind to SL API\n");
- return -1;
- }
-
- if ( init_rpid_avp(rpid_avp_param)<0 ) {
- LM_ERR("failed to init rpid AVP name\n");
- return -1;
- }
- if(cfg_declare("siputils", siputils_cfg_def, &default_siputils_cfg, cfg_sizeof(siputils), &siputils_cfg)){
- LM_ERR("Fail to declare the configuration\n");
- return -1;
- }
- return 0;
- }
- static void mod_destroy(void)
- {
- if (ring_lock) {
- lock_destroy(ring_lock);
- lock_dealloc((void *)ring_lock);
- ring_lock = NULL;
- }
- ring_destroy_hashtable();
- }
- /*!
- * \brief Bind function for the SIPUTILS API
- * \param api binded API
- * \return 0 on success, -1 on failure
- */
- int bind_siputils(siputils_api_t* api)
- {
- if (!api) {
- LM_ERR("invalid parameter value\n");
- return -1;
- }
- get_rpid_avp( &api->rpid_avp, &api->rpid_avp_type );
- api->has_totag = has_totag;
- api->is_uri_user_e164 = is_uri_user_e164;
- return 0;
- }
- /*
- * Fix set_uri_* function params: uri (writable pvar) and value (pvar)
- */
- static int fixup_set_uri(void** param, int param_no)
- {
- if (param_no == 1) {
- if (fixup_pvar_null(param, 1) != 0) {
- LM_ERR("failed to fixup uri pvar\n");
- return -1;
- }
- if (((pv_spec_t *)(*param))->setf == NULL) {
- LM_ERR("uri pvar is not writeble\n");
- return -1;
- }
- return 0;
- }
- if (param_no == 2) {
- return fixup_pvar_null(param, 1);
- }
- LM_ERR("invalid parameter number <%d>\n", param_no);
- return -1;
- }
- /*
- * Free set_uri_* params.
- */
- static int fixup_free_set_uri(void** param, int param_no)
- {
- return fixup_free_pvar_null(param, 1);
- }
- /*
- * Fix tel2sip function params: uri and hostpart pvars and
- * result writable pvar.
- */
- static int fixup_tel2sip(void** param, int param_no)
- {
- if ((param_no == 1) || (param_no == 2)) {
- if (fixup_var_str_12(param, 1) < 0) {
- LM_ERR("failed to fixup uri or hostpart pvar\n");
- return -1;
- }
- return 0;
- }
- if (param_no == 3) {
- if (fixup_pvar_null(param, 1) != 0) {
- LM_ERR("failed to fixup result pvar\n");
- return -1;
- }
- if (((pv_spec_t *)(*param))->setf == NULL) {
- LM_ERR("result pvar is not writeble\n");
- return -1;
- }
- return 0;
- }
- LM_ERR("invalid parameter number <%d>\n", param_no);
- return -1;
- }
- /* */
- static int fixup_get_uri_param(void** param, int param_no) {
- if (param_no == 1) {
- return fixup_str_null(param, 1);
- }
- if (param_no == 2) {
- if (fixup_pvar_null(param, 1) != 0) {
- LM_ERR("failed to fixup result pvar\n");
- return -1;
- }
- if (((pv_spec_t *)(*param))->setf == NULL) {
- LM_ERR("result pvar is not writeble\n");
- return -1;
- }
- return 0;
- }
- LM_ERR("invalid parameter number <%d>\n", param_no);
- return -1;
- }
- /* */
- static int free_fixup_get_uri_param(void** param, int param_no) {
- if (param_no == 1) {
- LM_WARN("free function has not been defined for spve\n");
- return 0;
- }
- if (param_no == 2) {
- return fixup_free_pvar_null(param, 1);
- }
- LM_ERR("invalid parameter number <%d>\n", param_no);
- return -1;
- }
- /* */
- static int fixup_option(void** param, int param_no) {
- char *option;
- unsigned int option_len, res;
- option = (char *)*param;
- option_len = strlen(option);
- if (param_no != 1) {
- LM_ERR("invalid parameter number <%d>\n", param_no);
- return -1;
- }
- switch (option_len) {
- case 4:
- if (strncasecmp(option, "path", 4) == 0)
- res = F_OPTION_TAG_PATH;
- else if (strncasecmp(option, "gruu", 4) == 0)
- res = F_OPTION_TAG_GRUU;
- else {
- LM_ERR("unknown option <%s>\n", option);
- return -1;
- }
- break;
- case 5:
- if (strncasecmp(option, "timer", 5) == 0)
- res = F_OPTION_TAG_TIMER;
- else {
- LM_ERR("unknown option <%s>\n", option);
- return -1;
- }
- break;
- case 6:
- if (strncasecmp(option, "100rel", 6) == 0)
- res = F_OPTION_TAG_100REL;
- else {
- LM_ERR("unknown option <%s>\n", option);
- return -1;
- }
- break;
- case 8:
- if (strncasecmp(option, "outbound", 8) == 0)
- res = F_OPTION_TAG_OUTBOUND;
- else {
- LM_ERR("unknown option <%s>\n", option);
- return -1;
- }
- break;
- case 9:
- if (strncasecmp(option, "eventlist", 9) == 0)
- res = F_OPTION_TAG_EVENTLIST;
- else {
- LM_ERR("unknown option <%s>\n", option);
- return -1;
- }
- break;
- default:
- LM_ERR("unknown option <%s>\n", option);
- return -1;
- }
- *param = (void *)(long)res;
- return 0;
- }
|