mirror of https://github.com/sipwise/kamailio.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
206 lines
6.7 KiB
206 lines
6.7 KiB
/*
|
|
* Route & Record-Route module
|
|
*
|
|
* $Id$
|
|
*
|
|
* Copyright (C) 2001-2003 FhG Fokus
|
|
*
|
|
* This file is part of ser, a free SIP server.
|
|
*
|
|
* ser 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
|
|
*
|
|
* For a license to use the ser software under conditions
|
|
* other than those described here, or to purchase support for this
|
|
* software, please contact iptel.org by e-mail at the following addresses:
|
|
* info@iptel.org
|
|
*
|
|
* ser 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
/* History:
|
|
* --------
|
|
* 2003-03-11 updated to the new module interface (andrei)
|
|
* 2003-03-16 flags export parameter added (janakj)
|
|
* 2003-03-19 all mallocs/frees replaced w/ pkg_malloc/pkg_free (andrei)
|
|
* 2003-04-01 Added record_route with ip address parameter (janakj)
|
|
* 2003-04-14 enable_full_lr parameter introduced (janakj)
|
|
*/
|
|
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include "rr_mod.h"
|
|
#include "../../sr_module.h"
|
|
#include "../../ut.h"
|
|
#include "../../error.h"
|
|
#include "../../mem/mem.h"
|
|
#include "loose.h"
|
|
#include "record.h"
|
|
#include "avp_cookie.h"
|
|
#include <sys/types.h> /* for regex */
|
|
#include <regex.h>
|
|
#include "../../script_cb.h"
|
|
#include "../../usr_avp.h"
|
|
#include "../../crc.h"
|
|
#include "../../select.h"
|
|
#include "../domain/domain.h"
|
|
#include "../../select_buf.h"
|
|
|
|
int append_fromtag = 1;
|
|
int enable_double_rr = 1; /* Enable using of 2 RR by default */
|
|
int enable_full_lr = 0; /* Disabled by default */
|
|
str add_username = STR_NULL; /* Do not add username by default */
|
|
char *cookie_filter = 0; /* filter cookies restored in loose_route, potential security problem */
|
|
str user_part_avp = STR_NULL; /* AVP identification where user part of Route URI is stored after loose/strict routing */
|
|
str next_route_avp = STR_NULL; /* AVP identification where next route (if exists) would be stored after loose/strict routing */
|
|
static str crc_secret_str = STR_NULL;
|
|
avp_ident_t user_part_avp_ident;
|
|
avp_ident_t next_route_avp_ident;
|
|
int rr_force_send_socket = 1; /* Force the send socket if 2 RR was added */
|
|
|
|
fparam_t* fparam_username = NULL;
|
|
|
|
MODULE_VERSION
|
|
|
|
static int mod_init(void);
|
|
|
|
domain_get_did_t dm_get_did = 0;
|
|
|
|
/*
|
|
* Exported functions
|
|
*/
|
|
/*
|
|
* I do not want people to use strict routing so it is disabled by default,
|
|
* you should always use loose routing, if you really need strict routing then
|
|
* you can replace the last zeroes with REQUEST_ROUTE to enable strict_route and
|
|
* record_route_strict. Don't do that unless you know what you are really doing !
|
|
* Oh, BTW, have I mentioned already that you shouldn't use strict routing ?
|
|
*/
|
|
static cmd_export_t cmds[] = {
|
|
{"loose_route", loose_route, 0, 0, REQUEST_ROUTE},
|
|
{"record_route", record_route, 0, 0, REQUEST_ROUTE},
|
|
{"record_route_preset", record_route_preset, 1, fixup_str_1, REQUEST_ROUTE},
|
|
{"record_route_strict" , record_route_strict, 0, 0, 0 },
|
|
{"remove_record_route", remove_record_route, 0, 0, REQUEST_ROUTE|FAILURE_ROUTE},
|
|
{0, 0, 0, 0, 0}
|
|
};
|
|
|
|
|
|
/*
|
|
* Exported parameters
|
|
*/
|
|
static param_export_t params[] ={
|
|
{"append_fromtag", PARAM_INT, &append_fromtag },
|
|
{"enable_double_rr", PARAM_INT, &enable_double_rr},
|
|
{"enable_full_lr", PARAM_INT, &enable_full_lr },
|
|
#ifdef ENABLE_USER_CHECK
|
|
{"ignore_user", PARAM_STR, &i_user },
|
|
#endif
|
|
{"add_username", PARAM_STR, &add_username },
|
|
{"cookie_filter", PARAM_STRING, &cookie_filter },
|
|
{"cookie_secret", PARAM_STR, &crc_secret_str },
|
|
{"user_part_avp", PARAM_STR, &user_part_avp },
|
|
{"next_route_avp", PARAM_STR, &next_route_avp },
|
|
{"force_send_socket", PARAM_INT, &rr_force_send_socket },
|
|
{0, 0, 0 }
|
|
};
|
|
|
|
|
|
struct module_exports exports = {
|
|
"rr",
|
|
cmds, /* Exported functions */
|
|
0, /* RPC methods */
|
|
params, /* Exported parameters */
|
|
mod_init, /* initialize module */
|
|
0, /* response function*/
|
|
0, /* destroy function */
|
|
0, /* oncancel function */
|
|
0 /* per-child init function */
|
|
};
|
|
|
|
|
|
static ABSTRACT_F(select_rrmod)
|
|
|
|
static int select_rr_avpcookie(str* res, struct select* s, struct sip_msg* msg) {
|
|
str *s2;
|
|
int ret;
|
|
s2 = rr_get_avp_cookies();
|
|
if (s2) {
|
|
ret = str_to_static_buffer(res, s2);
|
|
pkg_free(s2);
|
|
return ret;
|
|
}
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
static select_row_t rr_select_table[] = {
|
|
{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("rr"), select_rrmod, SEL_PARAM_EXPECTED},
|
|
{ select_rrmod, SEL_PARAM_STR, STR_STATIC_INIT("dialog_cookie"), select_rr_avpcookie, 0},
|
|
{ NULL, SEL_PARAM_INT, STR_NULL, NULL, 0}
|
|
};
|
|
|
|
|
|
static int mod_init(void)
|
|
{
|
|
void* param;
|
|
|
|
DBG("rr - initializing\n");
|
|
crc_secret = crcitt_string(crc_secret_str.s, crc_secret_str.len);
|
|
if (cookie_filter && strlen(cookie_filter)) {
|
|
cookie_filter_re = (regex_t*)pkg_malloc(sizeof(regex_t));
|
|
memset(cookie_filter_re, 0, sizeof(regex_t));
|
|
if (regcomp(cookie_filter_re, cookie_filter, REG_EXTENDED|REG_ICASE|REG_NEWLINE) ) {
|
|
LOG(L_ERR, "ERROR: %s : bad cookie_filter regex '%s'\n", exports.name, cookie_filter);
|
|
return E_BAD_RE;
|
|
}
|
|
}
|
|
|
|
memset (&user_part_avp_ident, 0, sizeof(avp_ident_t));
|
|
if (user_part_avp.s && user_part_avp.len) {
|
|
if (parse_avp_ident(&user_part_avp, &user_part_avp_ident)!=0) {
|
|
ERR("modparam \"user_part_avp\" : error while parsing\n");
|
|
return E_CFG;
|
|
}
|
|
}
|
|
memset (&next_route_avp_ident, 0, sizeof(avp_ident_t));
|
|
if (next_route_avp.s && next_route_avp.len) {
|
|
if (parse_avp_ident(&next_route_avp, &next_route_avp_ident)!=0) {
|
|
ERR("modparam \"next_route_avp\" : error while parsing\n");
|
|
return E_CFG;
|
|
}
|
|
}
|
|
avp_flag_dialog = register_avpflag(AVP_FLAG_DIALOG_COOKIE);
|
|
if (avp_flag_dialog == 0) {
|
|
LOG(L_ERR, "ERROR: %s: cannot register avpflag \"%s\"\n", exports.name, AVP_FLAG_DIALOG_COOKIE);
|
|
return E_CFG;
|
|
}
|
|
|
|
register_select_table(rr_select_table);
|
|
|
|
dm_get_did = (domain_get_did_t)find_export("get_did", 0, 0);
|
|
if (!dm_get_did) {
|
|
DBG("Domain module not found, rr support for multidomain disabled\n");
|
|
}
|
|
|
|
if (add_username.s) {
|
|
param=(void*)add_username.s;
|
|
if (fixup_var_str_12(¶m,1)<0) {
|
|
ERR("rr:mod_init:can't fixup add_username parameter\n");
|
|
return E_CFG;
|
|
}
|
|
fparam_username=(fparam_t*)param;
|
|
}
|
|
|
|
return 0;
|
|
}
|