Import unmodified vendor sources for correction and improvement.

Wed, 10 Feb 2010 21:14:04 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 10 Feb 2010 21:14:04 +0100
changeset 16
c5c55937e44c
parent 15
7ae8da2fe7c8
child 17
733187d496d0

Import unmodified vendor sources for correction and improvement.

opensips/modules/lcr/lcr_mod.c file | annotate | diff | comparison | revisions
opensips/modules/uac/auth.c file | annotate | diff | comparison | revisions
opensips/modules/uac/uac.c file | annotate | diff | comparison | revisions
opensips/scripts/db_berkeley/opensips/gw file | annotate | diff | comparison | revisions
opensips/scripts/dbtext/opensips/gw file | annotate | diff | comparison | revisions
opensips/scripts/mysql/lcr-create.sql file | annotate | diff | comparison | revisions
opensips/scripts/oracle/lcr-create.sql file | annotate | diff | comparison | revisions
opensips/scripts/postgres/lcr-create.sql file | annotate | diff | comparison | revisions
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/opensips/modules/lcr/lcr_mod.c	Wed Feb 10 21:14:04 2010 +0100
     1.3 @@ -0,0 +1,2187 @@
     1.4 +/*
     1.5 + * $Id: lcr_mod.c 6015 2009-08-22 21:45:06Z bogdan_iancu $
     1.6 + *
     1.7 + * Least Cost Routing module (also implements sequential forking)
     1.8 + *
     1.9 + * Copyright (C) 2005 Juha Heinanen
    1.10 + * Copyright (C) 2006 Voice Sistem SRL
    1.11 + *
    1.12 + * This file is part of opensips, a free SIP server.
    1.13 + *
    1.14 + * opensips is free software; you can redistribute it and/or modify
    1.15 + * it under the terms of the GNU General Public License as published by
    1.16 + * the Free Software Foundation; either version 2 of the License, or
    1.17 + * (at your option) any later version
    1.18 + *
    1.19 + * opensips is distributed in the hope that it will be useful,
    1.20 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.21 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1.22 + * GNU General Public License for more details.
    1.23 + *
    1.24 + * You should have received a copy of the GNU General Public License 
    1.25 + * along with this program; if not, write to the Free Software 
    1.26 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    1.27 + *
    1.28 + * History:
    1.29 + * -------
    1.30 + *  2005-02-14: Introduced lcr module (jh)
    1.31 + *  2005-02-20: Added sequential forking functions (jh)
    1.32 + *  2005-02-25: Added support for int AVP names, combined addr and port
    1.33 + *              AVPs (jh)
    1.34 + *  2005-07-28: Added support for gw URI scheme and transport, 
    1.35 + *              backport from ser (kd)
    1.36 + *  2005-08-20: Added support for gw prefixes (jh)
    1.37 + *  2005-09-03: Request-URI user part can be modified between load_gws()
    1.38 + *              and first next_gw() calls.
    1.39 + */
    1.40 +
    1.41 +#include <stdio.h>
    1.42 +#include <stdlib.h>
    1.43 +#include <string.h>
    1.44 +#include <sys/types.h>
    1.45 +#include <sys/socket.h>
    1.46 +#include <netinet/in.h>
    1.47 +#include <arpa/inet.h>
    1.48 +#include <regex.h>
    1.49 +#include "../../sr_module.h"
    1.50 +#include "../../dprint.h"
    1.51 +#include "../../ut.h"
    1.52 +#include "../../error.h"
    1.53 +#include "../../mem/mem.h"
    1.54 +#include "../../mem/shm_mem.h"
    1.55 +#include "../../db/db.h"
    1.56 +#include "../../usr_avp.h"
    1.57 +#include "../../parser/parse_uri.h"
    1.58 +#include "../../parser/parse_from.h"
    1.59 +#include "../../parser/msg_parser.h"
    1.60 +#include "../../action.h"
    1.61 +#include "../../qvalue.h"
    1.62 +#include "../../dset.h"
    1.63 +#include "../../ip_addr.h"
    1.64 +#include "../../resolve.h"
    1.65 +#include "../../mi/mi.h"
    1.66 +#include "../../mod_fix.h"
    1.67 +#include "../../socket_info.h"
    1.68 +#include "../../pvar.h"
    1.69 +#include "../../mod_fix.h"
    1.70 +#include "mi.h"
    1.71 +
    1.72 +
    1.73 +
    1.74 +/*
    1.75 + * Version of gw and lcr tables required by the module,
    1.76 + * increment this value if you change the table in
    1.77 + * an backwards incompatible way
    1.78 + */
    1.79 +#define GW_TABLE_VERSION 8
    1.80 +#define LCR_TABLE_VERSION 3
    1.81 +
    1.82 +/* usr_avp flag for sequential forking */
    1.83 +#define Q_FLAG      (1<<2)
    1.84 +
    1.85 +static void destroy(void);       /* Module destroy function */
    1.86 +static int mi_child_init(void);
    1.87 +static int mod_init(void);       /* Module initialization function */
    1.88 +static int fixstringloadgws(void **param, int param_count);
    1.89 +
    1.90 +int reload_gws ( void );
    1.91 +
    1.92 +#define GW_TABLE "gw"
    1.93 +
    1.94 +#define GW_NAME_COL "gw_name"
    1.95 +
    1.96 +#define GRP_ID_COL "grp_id"
    1.97 +
    1.98 +#define IP_ADDR_COL "ip_addr"
    1.99 +
   1.100 +#define PORT_COL "port"
   1.101 +
   1.102 +#define URI_SCHEME_COL "uri_scheme"
   1.103 +
   1.104 +#define TRANSPORT_COL "transport"
   1.105 +
   1.106 +#define STRIP_COL "strip"
   1.107 +
   1.108 +#define TAG_COL "tag"
   1.109 +
   1.110 +#define FLAGS_COL "flags"
   1.111 +
   1.112 +#define LCR_TABLE "lcr"
   1.113 +
   1.114 +#define PREFIX_COL "prefix"
   1.115 +
   1.116 +#define FROM_URI_COL "from_uri"
   1.117 +
   1.118 +#define PRIORITY_COL "priority"
   1.119 +
   1.120 +#define MAX_NO_OF_GWS 32
   1.121 +#define MAX_NO_OF_LCRS 256
   1.122 +#define MAX_PREFIX_LEN 256
   1.123 +#define MAX_TAG_LEN 16
   1.124 +#define MAX_FROM_URI_LEN 256
   1.125 +
   1.126 +/* Default module parameter values */
   1.127 +#define DEF_FR_INV_TIMER 90
   1.128 +#define DEF_FR_INV_TIMER_NEXT 30
   1.129 +#define DEF_PREFIX_MODE 0
   1.130 +
   1.131 +/*
   1.132 + * Type definitions
   1.133 + */
   1.134 +
   1.135 +typedef enum sip_protos uri_transport;
   1.136 +
   1.137 +struct gw_info {
   1.138 +    unsigned int ip_addr;
   1.139 +    unsigned int port;
   1.140 +    unsigned int grp_id;
   1.141 +    uri_type scheme;
   1.142 +    uri_transport transport;
   1.143 +    unsigned int strip;
   1.144 +    char tag[MAX_TAG_LEN + 1];
   1.145 +    unsigned short tag_len;
   1.146 +    unsigned int flags;
   1.147 +};
   1.148 +
   1.149 +struct lcr_info {
   1.150 +    char prefix[MAX_PREFIX_LEN + 1];
   1.151 +    unsigned short prefix_len;
   1.152 +    char from_uri[MAX_FROM_URI_LEN + 1];
   1.153 +    unsigned short from_uri_len;
   1.154 +    unsigned int grp_id;
   1.155 +    unsigned short priority;
   1.156 +    unsigned short end_record;
   1.157 +};
   1.158 +
   1.159 +struct prefix_regex {
   1.160 +	regex_t re;
   1.161 +	short int valid;
   1.162 +};
   1.163 +
   1.164 +struct from_uri_regex {
   1.165 +    regex_t re;
   1.166 +    short int valid;
   1.167 +};
   1.168 +
   1.169 +struct mi {
   1.170 +    int gw_index;
   1.171 +    int route_index;
   1.172 +    int randomizer;
   1.173 +};
   1.174 +
   1.175 +
   1.176 +/*
   1.177 + * Database variables
   1.178 + */
   1.179 +static db_con_t* db_handle = 0;   /* Database connection handle */
   1.180 +static db_func_t lcr_dbf;
   1.181 +
   1.182 +/*
   1.183 + * Module parameter variables
   1.184 + */
   1.185 +
   1.186 +/* database */
   1.187 +static str db_url           = str_init(DEFAULT_RODB_URL);
   1.188 +static str gw_table         = str_init(GW_TABLE);
   1.189 +static str gw_name_col      = str_init(GW_NAME_COL);
   1.190 +static str grp_id_col       = str_init(GRP_ID_COL);
   1.191 +static str ip_addr_col      = str_init(IP_ADDR_COL);
   1.192 +static str port_col         = str_init(PORT_COL);
   1.193 +static str uri_scheme_col   = str_init(URI_SCHEME_COL);
   1.194 +static str transport_col    = str_init(TRANSPORT_COL);
   1.195 +static str strip_col        = str_init(STRIP_COL);
   1.196 +static str tag_col          = str_init(TAG_COL);
   1.197 +static str flags_col        = str_init(FLAGS_COL);
   1.198 +static str lcr_table        = str_init(LCR_TABLE);
   1.199 +static str prefix_col       = str_init(PREFIX_COL);
   1.200 +static str from_uri_col     = str_init(FROM_URI_COL);
   1.201 +static str priority_col     = str_init(PRIORITY_COL);
   1.202 +
   1.203 +/* timer */
   1.204 +int fr_inv_timer      = DEF_FR_INV_TIMER;
   1.205 +int fr_inv_timer_next = DEF_FR_INV_TIMER_NEXT;
   1.206 +
   1.207 +/* avps */
   1.208 +static char *fr_inv_timer_avp_param = NULL;
   1.209 +static char *gw_uri_avp_param = NULL;
   1.210 +static char *ruri_user_avp_param = NULL;
   1.211 +static char *contact_avp_param = NULL;
   1.212 +static char *rpid_avp_param = NULL;
   1.213 +static char *flags_avp_param = NULL;
   1.214 +
   1.215 +/* prefix mode */
   1.216 +int prefix_mode_param = DEF_PREFIX_MODE;
   1.217 +
   1.218 +/*
   1.219 + * Other module types and variables
   1.220 + */
   1.221 +
   1.222 +struct contact {
   1.223 +    str uri;
   1.224 +    qvalue_t q;
   1.225 +    str dst_uri;
   1.226 +    str path;
   1.227 +    unsigned int flags;
   1.228 +    struct socket_info* sock;
   1.229 +    unsigned short q_flag;
   1.230 +    struct contact *next;
   1.231 +};
   1.232 +
   1.233 +static int     fr_inv_timer_avp_type;
   1.234 +static int_str fr_inv_timer_avp;
   1.235 +static int     gw_uri_avp_type;
   1.236 +static int_str gw_uri_avp;
   1.237 +static int     ruri_user_avp_type;
   1.238 +static int_str ruri_user_avp;
   1.239 +static int     contact_avp_type;
   1.240 +static int_str contact_avp;
   1.241 +static int     rpid_avp_type;
   1.242 +static int_str rpid_avp;
   1.243 +static int     flags_avp_type;
   1.244 +static int_str flags_avp;
   1.245 +
   1.246 +struct gw_info **gws;	/* Pointer to current gw table pointer */
   1.247 +struct gw_info *gws_1;	/* Pointer to gw table 1 */
   1.248 +struct gw_info *gws_2;	/* Pointer to gw table 2 */
   1.249 +
   1.250 +struct lcr_info **lcrs;  /* Pointer to current lcr table pointer */
   1.251 +struct lcr_info *lcrs_1; /* Pointer to lcr table 1 */
   1.252 +struct lcr_info *lcrs_2; /* Pointer to lcr table 2 */
   1.253 +
   1.254 +unsigned int *lcrs_ws_reload_counter;
   1.255 +unsigned int reload_counter;
   1.256 +
   1.257 +struct prefix_regex prefix_reg[MAX_NO_OF_LCRS];
   1.258 +struct from_uri_regex from_uri_reg[MAX_NO_OF_LCRS];
   1.259 +
   1.260 +/*
   1.261 + * Module functions that are defined later
   1.262 + */
   1.263 +static int load_gws_0(struct sip_msg* _m, char* _s1, char* _s2);
   1.264 +static int load_gws_1(struct sip_msg* _m, char* _s1, char* _s2);
   1.265 +static int load_gws_from_grp(struct sip_msg* _m, char* _s1, char* _s2);
   1.266 +static int next_gw(struct sip_msg* _m, char* _s1, char* _s2);
   1.267 +static int from_gw_0(struct sip_msg* _m, char* _s1, char* _s2);
   1.268 +static int from_gw_1(struct sip_msg* _m, char* _s1, char* _s2);
   1.269 +static int from_gw_grp(struct sip_msg* _m, char* _s1, char* _s2);
   1.270 +static int to_gw(struct sip_msg* _m, char* _s1, char* _s2);
   1.271 +static int to_gw_grp(struct sip_msg* _m, char* _s1, char* _s2);
   1.272 +static int load_contacts (struct sip_msg*, char*, char*);
   1.273 +static int next_contacts (struct sip_msg*, char*, char*);
   1.274 +
   1.275 +
   1.276 +/*
   1.277 + * Exported functions
   1.278 + */
   1.279 +static cmd_export_t cmds[] = {
   1.280 +	{"load_gws", (cmd_function)load_gws_0, 0, 0, 0, REQUEST_ROUTE},
   1.281 +	{"load_gws", (cmd_function)load_gws_1, 1, fixup_pvar_null,
   1.282 +		fixup_free_pvar_null, REQUEST_ROUTE},
   1.283 +	{"load_gws_from_grp", (cmd_function)load_gws_from_grp, 1,
   1.284 +	 fixstringloadgws, 0, REQUEST_ROUTE},
   1.285 +	{"next_gw", (cmd_function)next_gw, 0, 0, 0,
   1.286 +	 REQUEST_ROUTE | FAILURE_ROUTE},
   1.287 +	{"from_gw", (cmd_function)from_gw_0, 0, 0, 0,
   1.288 +	 REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE},
   1.289 +	{"from_gw", (cmd_function)from_gw_1, 1, fixup_pvar_null,
   1.290 +	 fixup_free_pvar_null, REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE},
   1.291 +	{"from_gw_grp", (cmd_function)from_gw_grp, 1, fixup_uint_null, 0,
   1.292 +	 REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE},
   1.293 +	{"to_gw", (cmd_function)to_gw, 0, 0, 0,
   1.294 +	 REQUEST_ROUTE | FAILURE_ROUTE},
   1.295 +	{"to_gw", (cmd_function)to_gw_grp, 1, fixup_uint_null, 0,
   1.296 +	 REQUEST_ROUTE | FAILURE_ROUTE},
   1.297 +	{"load_contacts", (cmd_function)load_contacts, 0, 0, 0,
   1.298 +	 REQUEST_ROUTE},
   1.299 +	{"next_contacts", (cmd_function)next_contacts, 0, 0, 0,
   1.300 +	 REQUEST_ROUTE | FAILURE_ROUTE},
   1.301 +	{0, 0, 0, 0, 0, 0}
   1.302 +};
   1.303 +
   1.304 +
   1.305 +/*
   1.306 + * Exported parameters
   1.307 + */
   1.308 +static param_export_t params[] = {
   1.309 +	{"db_url",                   STR_PARAM, &db_url.s       },
   1.310 +	{"gw_table",                 STR_PARAM, &gw_table.s     },
   1.311 +	{"gw_name_column",           STR_PARAM, &gw_name_col.s  },
   1.312 +	{"grp_id_column",            STR_PARAM, &grp_id_col.s   },
   1.313 +	{"ip_addr_column",           STR_PARAM, &ip_addr_col.s  },
   1.314 +	{"port_column",              STR_PARAM, &port_col.s     },
   1.315 +	{"uri_scheme_column",        STR_PARAM, &uri_scheme_col.s },
   1.316 +	{"transport_column",         STR_PARAM, &transport_col.s },
   1.317 +	{"strip_column",             STR_PARAM, &strip_col.s    },
   1.318 +	{"tag_column",               STR_PARAM, &tag_col.s      },
   1.319 +	{"flags_column",             STR_PARAM, &flags_col.s    },
   1.320 +	{"lcr_table",                STR_PARAM, &lcr_table.s    },
   1.321 +	{"prefix_column",            STR_PARAM, &prefix_col.s   },
   1.322 +	{"from_uri_column",          STR_PARAM, &from_uri_col.s },
   1.323 +	{"priority_column",          STR_PARAM, &priority_col.s },
   1.324 +	{"fr_inv_timer_avp",         STR_PARAM,	&fr_inv_timer_avp_param },
   1.325 +	{"gw_uri_avp",               STR_PARAM, &gw_uri_avp_param },
   1.326 +	{"ruri_user_avp",            STR_PARAM, &ruri_user_avp_param },
   1.327 +	{"contact_avp",              STR_PARAM, &contact_avp_param },
   1.328 +	{"rpid_avp",                 STR_PARAM, &rpid_avp_param },
   1.329 +	{"flags_avp",                STR_PARAM, &flags_avp_param },
   1.330 +	{"fr_inv_timer",             INT_PARAM, &fr_inv_timer },
   1.331 +	{"fr_inv_timer_next",        INT_PARAM,	&fr_inv_timer_next },
   1.332 +	{"prefix_mode",              INT_PARAM, &prefix_mode_param },
   1.333 +	{0, 0, 0}
   1.334 +};
   1.335 +
   1.336 +
   1.337 +/*
   1.338 + * Exported MI functions
   1.339 + */
   1.340 +static mi_export_t mi_cmds[] = {
   1.341 +	{ MI_LCR_RELOAD,  mi_lcr_reload,   MI_NO_INPUT_FLAG,  0,  mi_child_init },
   1.342 +	{ MI_LCR_DUMP,    mi_lcr_dump,     MI_NO_INPUT_FLAG,  0,  0 },
   1.343 +	{ 0, 0, 0, 0 ,0}
   1.344 +};
   1.345 +
   1.346 +
   1.347 +/*
   1.348 + * Module interface
   1.349 + */
   1.350 +struct module_exports exports = {
   1.351 +	"lcr", 
   1.352 +	MODULE_VERSION,
   1.353 +	DEFAULT_DLFLAGS, /* dlopen flags */
   1.354 +	cmds,      /* Exported functions */
   1.355 +	params,    /* Exported parameters */
   1.356 +	0,         /* exported statistics */
   1.357 +	mi_cmds,   /* exported MI functions */
   1.358 +	0,         /* exported pseudo-variables */
   1.359 +	0,         /* extra processes */
   1.360 +	mod_init,  /* module initialization function */
   1.361 +	0,         /* response function */
   1.362 +	destroy,   /* destroy function */
   1.363 +	0          /* child initialization function */
   1.364 +};
   1.365 +
   1.366 +
   1.367 +static int lcr_db_init(const str* db_url)
   1.368 +{	
   1.369 +	if (lcr_dbf.init==0){
   1.370 +		LM_CRIT("Null lcr_dbf\n");
   1.371 +		goto error;
   1.372 +	}
   1.373 +	db_handle=lcr_dbf.init(db_url);
   1.374 +	if (db_handle==0){
   1.375 +		LM_ERR("Unable to connect to the database\n");
   1.376 +		goto error;
   1.377 +	}
   1.378 +	return 0;
   1.379 +error:
   1.380 +	return -1;
   1.381 +}
   1.382 +
   1.383 +
   1.384 +
   1.385 +static int lcr_db_bind(const str* db_url)
   1.386 +{
   1.387 +    if (db_bind_mod(db_url, &lcr_dbf)<0){
   1.388 +	LM_ERR("Unable to bind to the database module\n");
   1.389 +	return -1;
   1.390 +    }
   1.391 +
   1.392 +    if (!DB_CAPABILITY(lcr_dbf, DB_CAP_QUERY)) {
   1.393 +	LM_ERR("Database module does not implement 'query' function\n");
   1.394 +	return -1;
   1.395 +    }
   1.396 +
   1.397 +    return 0;
   1.398 +}
   1.399 +
   1.400 +
   1.401 +static void lcr_db_close(void)
   1.402 +{
   1.403 +	if (db_handle && lcr_dbf.close){
   1.404 +		lcr_dbf.close(db_handle);
   1.405 +		db_handle=0;
   1.406 +	}
   1.407 +}
   1.408 +
   1.409 +
   1.410 +static int mi_child_init(void)
   1.411 +{
   1.412 +	return lcr_db_init(&db_url);
   1.413 +}
   1.414 +
   1.415 +
   1.416 +/*
   1.417 + * Module initialization function that is called before the main process forks
   1.418 + */
   1.419 +static int mod_init(void)
   1.420 +{
   1.421 +	int i;
   1.422 +    pv_spec_t avp_spec;
   1.423 +    str s;
   1.424 +    unsigned short avp_flags;
   1.425 +
   1.426 +    LM_DBG("Initializing\n");
   1.427 +
   1.428 +    /* Update length of module variables */
   1.429 +    db_url.len = strlen(db_url.s);
   1.430 +    gw_table.len = strlen(gw_table.s);
   1.431 +    gw_name_col.len = strlen(gw_name_col.s);
   1.432 +    grp_id_col.len = strlen(grp_id_col.s);
   1.433 +    ip_addr_col.len = strlen(ip_addr_col.s);
   1.434 +    port_col.len = strlen(port_col.s);
   1.435 +    uri_scheme_col.len = strlen(uri_scheme_col.s);
   1.436 +    transport_col.len = strlen(transport_col.s);
   1.437 +    strip_col.len = strlen(strip_col.s);
   1.438 +    tag_col.len = strlen(tag_col.s);
   1.439 +    flags_col.len = strlen(flags_col.s);
   1.440 +    lcr_table.len = strlen(lcr_table.s);
   1.441 +    prefix_col.len = strlen(prefix_col.s);
   1.442 +    from_uri_col.len = strlen(from_uri_col.s);
   1.443 +    priority_col.len = strlen(priority_col.s);
   1.444 +
   1.445 +    /* Bind database */
   1.446 +    if (lcr_db_bind(&db_url)) {
   1.447 +	LM_ERR("No database module found\n");
   1.448 +	return -1;
   1.449 +    }
   1.450 +
   1.451 +    /* Check value of prefix_mode */
   1.452 +    if ((prefix_mode_param != 0) && (prefix_mode_param != 1)) {
   1.453 +	LM_ERR("Invalid prefix_mode value <%d>\n", prefix_mode_param);
   1.454 +	return -1;
   1.455 +    }
   1.456 +
   1.457 +    /* Process AVP params */
   1.458 +    if (fr_inv_timer_avp_param && *fr_inv_timer_avp_param) {
   1.459 +	s.s = fr_inv_timer_avp_param; s.len = strlen(s.s);
   1.460 +	if (pv_parse_spec(&s, &avp_spec)==0
   1.461 +	    || avp_spec.type!=PVT_AVP) {
   1.462 +	    LM_ERR("Malformed or non AVP definition <%s>\n",
   1.463 +		   fr_inv_timer_avp_param);
   1.464 +	    return -1;
   1.465 +	}
   1.466 +	
   1.467 +	if(pv_get_avp_name(0, &(avp_spec.pvp), &fr_inv_timer_avp, &avp_flags)!=0) {
   1.468 +	    LM_ERR("Invalid AVP definition <%s>\n", fr_inv_timer_avp_param);
   1.469 +	    return -1;
   1.470 +	}
   1.471 +	fr_inv_timer_avp_type = avp_flags;
   1.472 +    } else {
   1.473 +	LM_ERR("AVP fr_inv_timer_avp has not been defined\n");
   1.474 +	return -1;
   1.475 +    }
   1.476 +
   1.477 +    if (gw_uri_avp_param && *gw_uri_avp_param) {
   1.478 +	s.s = gw_uri_avp_param; s.len = strlen(s.s);
   1.479 +	if (pv_parse_spec(&s, &avp_spec)==0
   1.480 +	    || avp_spec.type!=PVT_AVP) {
   1.481 +	    LM_ERR("Malformed or non AVP definition <%s>\n", gw_uri_avp_param);
   1.482 +	    return -1;
   1.483 +	}
   1.484 +	
   1.485 +	if(pv_get_avp_name(0, &(avp_spec.pvp), &gw_uri_avp, &avp_flags)!=0) {
   1.486 +	    LM_ERR("Invalid AVP definition <%s>\n", gw_uri_avp_param);
   1.487 +	    return -1;
   1.488 +	}
   1.489 +	gw_uri_avp_type = avp_flags;
   1.490 +    } else {
   1.491 +	LM_ERR("AVP gw_uri_avp has not been defined\n");
   1.492 +	return -1;
   1.493 +    }
   1.494 +
   1.495 +    if (ruri_user_avp_param && *ruri_user_avp_param) {
   1.496 +	s.s = ruri_user_avp_param; s.len = strlen(s.s);
   1.497 +	if (pv_parse_spec(&s, &avp_spec)==0
   1.498 +	    || avp_spec.type!=PVT_AVP) {
   1.499 +	    LM_ERR("Malformed or non AVP definition <%s>\n",
   1.500 +		   ruri_user_avp_param);
   1.501 +	    return -1;
   1.502 +	}
   1.503 +	
   1.504 +	if(pv_get_avp_name(0, &(avp_spec.pvp), &ruri_user_avp, &avp_flags)!=0) {
   1.505 +	    LM_ERR("Invalid AVP definition <%s>\n", ruri_user_avp_param);
   1.506 +	    return -1;
   1.507 +	}
   1.508 +	ruri_user_avp_type = avp_flags;
   1.509 +    } else {
   1.510 +	LM_ERR("AVP ruri_user_avp has not been defined\n");
   1.511 +	return -1;
   1.512 +    }
   1.513 +
   1.514 +    if (contact_avp_param && *contact_avp_param) {
   1.515 +	s.s = contact_avp_param; s.len = strlen(s.s);
   1.516 +	if (pv_parse_spec(&s, &avp_spec)==0
   1.517 +	    || avp_spec.type!=PVT_AVP) {
   1.518 +	    LM_ERR("Malformed or non AVP definition <%s>\n",
   1.519 +		   contact_avp_param);
   1.520 +	    return -1;
   1.521 +	}
   1.522 +	
   1.523 +	if(pv_get_avp_name(0, &(avp_spec.pvp), &contact_avp, &avp_flags)!=0) {
   1.524 +	    LM_ERR("Invalid AVP definition <%s>\n", contact_avp_param);
   1.525 +	    return -1;
   1.526 +	}
   1.527 +	contact_avp_type = avp_flags;
   1.528 +    } else {
   1.529 +	LM_ERR("AVP contact_avp has not been defined\n");
   1.530 +	return -1;
   1.531 +    }
   1.532 +
   1.533 +    if (rpid_avp_param && *rpid_avp_param) {
   1.534 +	s.s = rpid_avp_param; s.len = strlen(s.s);
   1.535 +	if (pv_parse_spec(&s, &avp_spec)==0
   1.536 +	    || avp_spec.type!=PVT_AVP) {
   1.537 +	    LM_ERR("Malformed or non AVP definition <%s>\n", rpid_avp_param);
   1.538 +	    return -1;
   1.539 +	}
   1.540 +	
   1.541 +	if(pv_get_avp_name(0, &(avp_spec.pvp), &rpid_avp, &avp_flags)!=0) {
   1.542 +	    LM_ERR("Invalid AVP definition <%s>\n", rpid_avp_param);
   1.543 +	    return -1;
   1.544 +	}
   1.545 +	rpid_avp_type = avp_flags;
   1.546 +    } else {
   1.547 +	LM_ERR("AVP rpid_avp has not been defined\n");
   1.548 +	return -1;
   1.549 +    }
   1.550 +
   1.551 +    if (flags_avp_param && *flags_avp_param) {
   1.552 +	s.s = flags_avp_param; s.len = strlen(s.s);
   1.553 +	if (pv_parse_spec(&s, &avp_spec)==0
   1.554 +	    || avp_spec.type!=PVT_AVP) {
   1.555 +	    LM_ERR("Malformed or non AVP definition <%s>\n", flags_avp_param);
   1.556 +	    return -1;
   1.557 +	}
   1.558 +	
   1.559 +	if(pv_get_avp_name(0, &(avp_spec.pvp), &flags_avp, &avp_flags)!=0) {
   1.560 +	    LM_ERR("Invalid AVP definition <%s>\n", flags_avp_param);
   1.561 +	    return -1;
   1.562 +	}
   1.563 +	flags_avp_type = avp_flags;
   1.564 +    } else {
   1.565 +	LM_ERR("AVP flags_avp has not been defined\n");
   1.566 +	return -1;
   1.567 +    }
   1.568 +
   1.569 +    /* Check table version */
   1.570 +	db_con_t* dbh;
   1.571 +	if (lcr_dbf.init==0){
   1.572 +		LM_CRIT("Unbound database\n");
   1.573 +		return -1;
   1.574 +	}
   1.575 +	dbh=lcr_dbf.init(&db_url);
   1.576 +	if (dbh==0){
   1.577 +		LM_ERR("Unable to open database connection\n");
   1.578 +		return -1;
   1.579 +	}
   1.580 +	if((db_check_table_version(&lcr_dbf, dbh, &gw_table, GW_TABLE_VERSION) < 0) ||
   1.581 +		(db_check_table_version(&lcr_dbf, dbh, &lcr_table, LCR_TABLE_VERSION) < 0)) {
   1.582 +			LM_ERR("error during table version check.\n");
   1.583 +			lcr_dbf.close(dbh);
   1.584 +			goto err;
   1.585 +    }
   1.586 +	lcr_dbf.close(dbh);
   1.587 +
   1.588 +    /* Initializing gw tables and gw table pointer variable */
   1.589 +    gws_1 = (struct gw_info *)shm_malloc(sizeof(struct gw_info) *
   1.590 +					 (MAX_NO_OF_GWS + 1));
   1.591 +    if (gws_1 == 0) {
   1.592 +	LM_ERR("No memory for gw table\n");
   1.593 +	goto err;
   1.594 +    }
   1.595 +    gws_2 = (struct gw_info *)shm_malloc(sizeof(struct gw_info) *
   1.596 +					 (MAX_NO_OF_GWS + 1));
   1.597 +    if (gws_2 == 0) {
   1.598 +	LM_ERR("No memory for gw table\n");
   1.599 +	goto err;
   1.600 +    }
   1.601 +    for (i = 0; i < MAX_NO_OF_GWS + 1; i++) {
   1.602 +	gws_1[i].ip_addr = gws_2[i].ip_addr = 0;
   1.603 +    }
   1.604 +    gws = (struct gw_info **)shm_malloc(sizeof(struct gw_info *));
   1.605 +    if (gws == 0) {
   1.606 +	LM_ERR("No memory for gw table pointer\n");
   1.607 +    }
   1.608 +    *gws = gws_1;
   1.609 +
   1.610 +    /* Initializing lcr tables and lcr table pointer variable */
   1.611 +    lcrs_1 = (struct lcr_info *)shm_malloc(sizeof(struct lcr_info) *
   1.612 +					   (MAX_NO_OF_LCRS + 1));
   1.613 +    if (lcrs_1 == 0) {
   1.614 +	LM_ERR("No memory for lcr table\n");
   1.615 +	goto err;
   1.616 +    }
   1.617 +    lcrs_2 = (struct lcr_info *)shm_malloc(sizeof(struct lcr_info) *
   1.618 +					   (MAX_NO_OF_LCRS + 1));
   1.619 +    if (lcrs_2 == 0) {
   1.620 +	LM_ERR("No memory for lcr table\n");
   1.621 +	goto err;
   1.622 +    }
   1.623 +    for (i = 0; i < MAX_NO_OF_LCRS + 1; i++) {
   1.624 +	lcrs_1[i].end_record = lcrs_2[i].end_record = 0;
   1.625 +    }
   1.626 +    lcrs = (struct lcr_info **)shm_malloc(sizeof(struct lcr_info *));
   1.627 +    if (lcrs == 0) {
   1.628 +	LM_ERR("No memory for lcr table pointer\n");
   1.629 +	goto err;
   1.630 +    }
   1.631 +    *lcrs = lcrs_1;
   1.632 +
   1.633 +    lcrs_ws_reload_counter = (unsigned int *)shm_malloc(sizeof(unsigned int));
   1.634 +    if (lcrs_ws_reload_counter == 0) {
   1.635 +	LM_ERR("No memory for reload counter\n");
   1.636 +	goto err;
   1.637 +    }
   1.638 +    *lcrs_ws_reload_counter = reload_counter = 0;
   1.639 +
   1.640 +    memset(prefix_reg, 0, sizeof(struct prefix_regex) * MAX_NO_OF_LCRS);
   1.641 +    memset(from_uri_reg, 0, sizeof(struct from_uri_regex) * MAX_NO_OF_LCRS);
   1.642 +
   1.643 +    /* First reload */
   1.644 +    if (reload_gws() == -1) {
   1.645 +	LM_CRIT("Failed to reload gateways and routes\n");
   1.646 +	goto err;
   1.647 +    }
   1.648 +
   1.649 +    return 0;
   1.650 +
   1.651 +err:
   1.652 +    return -1;
   1.653 +}
   1.654 +
   1.655 +
   1.656 +static void destroy(void)
   1.657 +{
   1.658 +	lcr_db_close();
   1.659 +}
   1.660 +
   1.661 +/*
   1.662 + * Sort lcr records by prefix_len and priority.
   1.663 + */
   1.664 +static int comp_lcrs(const void *m1, const void *m2)
   1.665 +{
   1.666 +    int result = -1;
   1.667 +
   1.668 +    struct mi *mi1 = (struct mi *) m1;
   1.669 +    struct mi *mi2 = (struct mi *) m2;
   1.670 +
   1.671 +    struct lcr_info lcr_record1 = (*lcrs)[mi1->route_index];
   1.672 +    struct lcr_info lcr_record2 = (*lcrs)[mi2->route_index];
   1.673 +
   1.674 +    if (prefix_mode_param == 0) {
   1.675 +        /* Sort by prefix. */
   1.676 +        if (lcr_record1.prefix_len > lcr_record2.prefix_len) {
   1.677 +	    result = 1;
   1.678 +        } else if (lcr_record1.prefix_len == lcr_record2.prefix_len) {
   1.679 +	    /* Sort by priority. */
   1.680 +	    if (lcr_record1.priority < lcr_record2.priority) {
   1.681 +	        result = 1;
   1.682 +	    } else if (lcr_record1.priority == lcr_record2.priority) {
   1.683 +	        /* Nothing to do. */
   1.684 +	        result = 0;
   1.685 +	    }
   1.686 +        }
   1.687 +    } else {
   1.688 +        if (lcr_record1.priority < lcr_record2.priority) {
   1.689 +	    result = 1;
   1.690 +	} else if (lcr_record1.priority == lcr_record2.priority) {
   1.691 +	    /* Nothing to do. */
   1.692 +	    result = 0;
   1.693 +	}
   1.694 +    }
   1.695 +
   1.696 +    return result;
   1.697 +}
   1.698 +
   1.699 +/*
   1.700 + * Sort lcr records by rand table.
   1.701 + */
   1.702 +static int rand_lcrs(const void *m1, const void *m2)
   1.703 +{
   1.704 +    int result = -1;
   1.705 +
   1.706 +    struct mi mi1 = *((struct mi *) m1);
   1.707 +    struct mi mi2 = *((struct mi *) m2);
   1.708 +
   1.709 +    if (mi1.randomizer > mi2.randomizer) {
   1.710 +	result = 1;
   1.711 +    } else if (mi1.randomizer == mi2.randomizer) {
   1.712 +	result = 0;
   1.713 +    }
   1.714 +
   1.715 +    return result;
   1.716 +}
   1.717 +
   1.718 +/*
   1.719 + * regcomp each prefix.
   1.720 + */
   1.721 +static int load_prefix_regex(void)
   1.722 +{
   1.723 +    int i, status, result = 0;
   1.724 +
   1.725 +    for (i = 0; i < MAX_NO_OF_LCRS; i++) {
   1.726 +	if ((*lcrs)[i].end_record != 0) {
   1.727 +	    break;
   1.728 +	}
   1.729 +	if (prefix_reg[i].valid) {
   1.730 +	    regfree(&(prefix_reg[i].re));
   1.731 +	    prefix_reg[i].valid = 0;
   1.732 +	}
   1.733 +	memset(&(prefix_reg[i].re), 0, sizeof(regex_t));
   1.734 +	if ((status=regcomp(&(prefix_reg[i].re),(*lcrs)[i].prefix,0))!=0){
   1.735 +	    LM_ERR("bad prefix re <%s>, regcomp returned %d (check regex.h)\n",
   1.736 +		(*lcrs)[i].prefix, status);
   1.737 +	    result = -1;
   1.738 +	    break;
   1.739 +	}
   1.740 +	prefix_reg[i].valid = 1;
   1.741 +    }
   1.742 +
   1.743 +    return result;
   1.744 +}
   1.745 +
   1.746 +/*
   1.747 + * regcomp each from_uri.
   1.748 + */
   1.749 +static int load_from_uri_regex(void)
   1.750 +{
   1.751 +    int i, status, result = 0;
   1.752 +
   1.753 +    for (i = 0; i < MAX_NO_OF_LCRS; i++) {
   1.754 +	if ((*lcrs)[i].end_record != 0) {
   1.755 +	    break;
   1.756 +	}
   1.757 +	if (from_uri_reg[i].valid) {
   1.758 +	    regfree(&(from_uri_reg[i].re));
   1.759 +	    from_uri_reg[i].valid = 0;
   1.760 +	}
   1.761 +	memset(&(from_uri_reg[i].re), 0, sizeof(regex_t));
   1.762 +	if ((status=regcomp(&(from_uri_reg[i].re),(*lcrs)[i].from_uri,0))!=0){
   1.763 +	    LM_ERR("Bad from_uri re <%s>, regcomp returned %d (check regex.h)\n",
   1.764 +	    	(*lcrs)[i].from_uri, status);
   1.765 +	    result = -1;
   1.766 +	    break;
   1.767 +	}
   1.768 +	from_uri_reg[i].valid = 1;
   1.769 +    }
   1.770 +
   1.771 +    if (result != -1) {
   1.772 +	reload_counter = *lcrs_ws_reload_counter;
   1.773 +    }
   1.774 +    return result;
   1.775 +}
   1.776 +
   1.777 +static int load_all_regex(void)
   1.778 +{
   1.779 +	int result =0;
   1.780 +
   1.781 +	if (prefix_mode_param != 0) {
   1.782 +		result = load_prefix_regex();
   1.783 +	}
   1.784 +
   1.785 +	if (result == 0) {
   1.786 +		result = load_from_uri_regex();
   1.787 +	} else {
   1.788 +		LM_ERR("Unable to load prefix regex\n");
   1.789 +	}
   1.790 +
   1.791 +	if (result == 0) {
   1.792 +		reload_counter = *lcrs_ws_reload_counter;
   1.793 +	} else {
   1.794 +		LM_ERR("Unable to load from_uri regex\n");
   1.795 +	}
   1.796 +
   1.797 +	return result;
   1.798 +}
   1.799 +
   1.800 +/*
   1.801 + * Reload gws to unused gw table and lcrs to unused lcr table, and, when done
   1.802 + * make unused gw and lcr table the one in use.
   1.803 + */
   1.804 +int reload_gws(void)
   1.805 +{
   1.806 +    unsigned int i, port, strip, tag_len, prefix_len, from_uri_len,
   1.807 +    grp_id, priority;
   1.808 +    struct in_addr ip_addr;
   1.809 +    unsigned int flags;
   1.810 +    uri_type scheme;
   1.811 +    uri_transport transport;
   1.812 +    db_con_t* dbh;
   1.813 +    char *tag, *prefix, *from_uri;
   1.814 +    db_res_t* res = NULL;
   1.815 +    db_row_t* row;
   1.816 +    db_key_t gw_cols[8];
   1.817 +    db_key_t lcr_cols[4];
   1.818 +
   1.819 +    gw_cols[0] = &ip_addr_col;
   1.820 +    gw_cols[1] = &port_col;
   1.821 +    gw_cols[2] = &uri_scheme_col;
   1.822 +    gw_cols[3] = &transport_col;
   1.823 +    gw_cols[4] = &strip_col;
   1.824 +    gw_cols[5] = &tag_col;
   1.825 +    /* FIXME: is this ok if we have different names for grp_id
   1.826 +       in the two tables? (ge vw lcr) */
   1.827 +    gw_cols[6] = &grp_id_col;
   1.828 +    gw_cols[7] = &flags_col;
   1.829 +
   1.830 +    lcr_cols[0] = &prefix_col;
   1.831 +    lcr_cols[1] = &from_uri_col;
   1.832 +    /* FIXME: is this ok if we have different names for grp_id
   1.833 +       in the two tables? (ge vw lcr) */
   1.834 +    lcr_cols[2] = &grp_id_col;
   1.835 +    lcr_cols[3] = &priority_col;
   1.836 +
   1.837 +    if (lcr_dbf.init==0){
   1.838 +	LM_CRIT("Unbound database\n");
   1.839 +	return -1;
   1.840 +    }
   1.841 +    dbh=lcr_dbf.init(&db_url);
   1.842 +    if (dbh==0){
   1.843 +	LM_ERR("Unable to open database connection\n");
   1.844 +	return -1;
   1.845 +    }
   1.846 +
   1.847 +    if (lcr_dbf.use_table(dbh, &gw_table) < 0) {
   1.848 +	LM_ERR("Error while trying to use gw table\n");
   1.849 +	return -1;
   1.850 +    }
   1.851 +
   1.852 +    if (lcr_dbf.query(dbh, NULL, 0, NULL, gw_cols, 0, 8, 0, &res) < 0) {
   1.853 +	    LM_ERR("Failed to query gw data\n");
   1.854 +	    lcr_dbf.close(dbh);
   1.855 +	    return -1;
   1.856 +    }
   1.857 +
   1.858 +    if (RES_ROW_N(res) + 1 > MAX_NO_OF_GWS) {
   1.859 +	    LM_ERR("Too many gateways\n");
   1.860 +	    lcr_dbf.free_result(dbh, res);
   1.861 +	    lcr_dbf.close(dbh);
   1.862 +	    return -1;
   1.863 +    }
   1.864 +
   1.865 +    for (i = 0; i < RES_ROW_N(res); i++) {
   1.866 +	row = RES_ROWS(res) + i;
   1.867 +	if (!((VAL_TYPE(ROW_VALUES(row)) == DB_STRING) &&
   1.868 +	      !VAL_NULL(ROW_VALUES(row)) &&
   1.869 +	      inet_aton((char *)VAL_STRING(ROW_VALUES(row)), &ip_addr) != 0)) {
   1.870 +	    LM_ERR("Invalid IP address of gw <%s>\n",
   1.871 +		   (char *)VAL_STRING(ROW_VALUES(row)));
   1.872 +	    lcr_dbf.free_result(dbh, res);
   1.873 +	    lcr_dbf.close(dbh);
   1.874 +	    return -1;
   1.875 +	}
   1.876 +	if (VAL_NULL(ROW_VALUES(row) + 1) == 1) {
   1.877 +	    port = 0;
   1.878 +	} else {
   1.879 +	    port = (unsigned int)VAL_INT(ROW_VALUES(row) + 1);
   1.880 +	}
   1.881 +	if (port > 65536) {
   1.882 +	    LM_ERR("Port of gw is too large <%u>\n", port);
   1.883 +	    lcr_dbf.free_result(dbh, res);
   1.884 +	    lcr_dbf.close(dbh);
   1.885 +	    return -1;
   1.886 +	}
   1.887 +	if (VAL_NULL(ROW_VALUES(row) + 2) == 1) {
   1.888 +	    scheme = SIP_URI_T;
   1.889 +	} else {
   1.890 +	    scheme = (uri_type)VAL_INT(ROW_VALUES(row) + 2);
   1.891 +	    if ((scheme != SIP_URI_T) && (scheme != SIPS_URI_T)) {
   1.892 +		LM_ERR("Unknown or unsupported URI scheme <%u>\n",
   1.893 +		       (unsigned int)scheme);
   1.894 +		lcr_dbf.free_result(dbh, res);
   1.895 +		lcr_dbf.close(dbh);
   1.896 +		return -1;
   1.897 +	    }
   1.898 +	}
   1.899 +	if (VAL_NULL(ROW_VALUES(row) + 3) == 1) {
   1.900 +	    transport = PROTO_NONE;
   1.901 +	} else {
   1.902 +	    transport = (uri_transport)VAL_INT(ROW_VALUES(row) + 3);
   1.903 +	    if ((transport != PROTO_UDP) && (transport != PROTO_TCP) &&
   1.904 +		(transport != PROTO_TLS)) {
   1.905 +		LM_ERR("Unknown or unsupported transport <%u>\n",
   1.906 +		       (unsigned int)transport);
   1.907 +		lcr_dbf.free_result(dbh, res);
   1.908 +		lcr_dbf.close(dbh);
   1.909 +		return -1;
   1.910 +	    }
   1.911 +	}
   1.912 +	if (VAL_NULL(ROW_VALUES(row) + 4) == 1) {
   1.913 +	    strip = 0;
   1.914 +	} else {
   1.915 +	    strip = (unsigned int)VAL_INT(ROW_VALUES(row) + 4);
   1.916 +	}
   1.917 +	if (VAL_NULL(ROW_VALUES(row) + 5) == 1) {
   1.918 +	    tag_len = 0;
   1.919 +	    tag = (char *)0;
   1.920 +	} else {
   1.921 +	    tag = (char *)VAL_STRING(ROW_VALUES(row) + 5);
   1.922 +	    tag_len = strlen(tag);
   1.923 +	    if (tag_len > MAX_TAG_LEN) {
   1.924 +		LM_ERR("Too long gw tag <%u>\n", tag_len);
   1.925 +		lcr_dbf.free_result(dbh, res);
   1.926 +		lcr_dbf.close(dbh);
   1.927 +		return -1;
   1.928 +	    }
   1.929 +	}
   1.930 +	if (VAL_NULL(ROW_VALUES(row) + 6) == 1) {
   1.931 +	    grp_id = 0;
   1.932 +	} else {
   1.933 +	    grp_id = VAL_INT(ROW_VALUES(row) + 6);
   1.934 +	}
   1.935 +	if (!VAL_NULL(ROW_VALUES(row) + 7) &&
   1.936 +	    (VAL_TYPE(ROW_VALUES(row) + 7) == DB_INT)) {
   1.937 +	    flags = (unsigned int)VAL_INT(ROW_VALUES(row) + 7);
   1.938 +	} else {
   1.939 +	    LM_ERR("Attribute flags is NULL or non-int\n");
   1.940 +	    lcr_dbf.free_result(dbh, res);
   1.941 +	    lcr_dbf.close(dbh);
   1.942 +	    return -1;
   1.943 +	}
   1.944 +	if (*gws == gws_1) {
   1.945 +	    gws_2[i].ip_addr = (unsigned int)ip_addr.s_addr;
   1.946 +	    gws_2[i].port = port;
   1.947 +	    gws_2[i].grp_id = grp_id;
   1.948 +	    gws_2[i].scheme = scheme;
   1.949 +	    gws_2[i].transport = transport;
   1.950 +	    gws_2[i].flags = flags;
   1.951 +	    gws_2[i].strip = strip;
   1.952 +	    gws_2[i].tag_len = tag_len;
   1.953 +	    if (tag_len)
   1.954 +		memcpy(&(gws_2[i].tag[0]), tag, tag_len);
   1.955 +	} else {
   1.956 +	    gws_1[i].ip_addr = (unsigned int)ip_addr.s_addr;
   1.957 +	    gws_1[i].port = port;
   1.958 +	    gws_1[i].grp_id = grp_id;
   1.959 +	    gws_1[i].scheme = scheme;
   1.960 +	    gws_1[i].transport = transport;
   1.961 +	    gws_1[i].flags = flags;
   1.962 +	    gws_1[i].strip = strip;
   1.963 +	    gws_1[i].tag_len = tag_len;
   1.964 +	    if (tag_len)
   1.965 +		memcpy(&(gws_1[i].tag[0]), tag, tag_len);
   1.966 +	}
   1.967 +    }
   1.968 +
   1.969 +    lcr_dbf.free_result(dbh, res);
   1.970 +
   1.971 +    if (*gws == gws_1) {
   1.972 +	gws_2[i].ip_addr = 0;
   1.973 +	*gws = gws_2;
   1.974 +    } else {
   1.975 +	gws_1[i].ip_addr = 0;
   1.976 +	*gws = gws_1;
   1.977 +    }
   1.978 +
   1.979 +
   1.980 +    if (lcr_dbf.use_table(dbh, &lcr_table) < 0) {
   1.981 +	LM_ERR("Error while trying to use lcr table\n");
   1.982 +	return -1;
   1.983 +    }
   1.984 +
   1.985 +    if (lcr_dbf.query(dbh, NULL, 0, NULL, lcr_cols, 0, 4, 0, &res) < 0) {
   1.986 +	LM_ERR("Failed to query lcr data\n");
   1.987 +	lcr_dbf.close(dbh);
   1.988 +	return -1;
   1.989 +    }
   1.990 +
   1.991 +    if (RES_ROW_N(res) + 1 > MAX_NO_OF_LCRS) {
   1.992 +	LM_ERR("Too many lcr entries <%d>\n", RES_ROW_N(res));
   1.993 +	lcr_dbf.free_result(dbh, res);
   1.994 +	lcr_dbf.close(dbh);
   1.995 +	return -1;
   1.996 +    }
   1.997 +    for (i = 0; i < RES_ROW_N(res); i++) {
   1.998 +	row = RES_ROWS(res) + i;
   1.999 +	if (VAL_NULL(ROW_VALUES(row)) == 1) {
  1.1000 +	    prefix_len = 0;
  1.1001 +	    prefix = 0;
  1.1002 +	} else {
  1.1003 +	    prefix = (char *)VAL_STRING(ROW_VALUES(row));
  1.1004 +	    prefix_len = strlen(prefix);
  1.1005 +	    if (prefix_len > MAX_PREFIX_LEN) {
  1.1006 +		LM_ERR("Too long lcr prefix <%u>\n", prefix_len);
  1.1007 +		lcr_dbf.free_result(dbh, res);
  1.1008 +		lcr_dbf.close(dbh);
  1.1009 +		return -1;
  1.1010 +	    }
  1.1011 +	}
  1.1012 +	if (VAL_NULL(ROW_VALUES(row) + 1) == 1) {
  1.1013 +	    from_uri_len = 0;
  1.1014 +	    from_uri = 0;
  1.1015 +	} else {
  1.1016 +	    from_uri = (char *)VAL_STRING(ROW_VALUES(row) + 1);
  1.1017 +	    from_uri_len = strlen(from_uri);
  1.1018 +	    if (from_uri_len > MAX_FROM_URI_LEN) {
  1.1019 +		LM_ERR("Too long from_uri <%u>\n", from_uri_len);
  1.1020 +		lcr_dbf.free_result(dbh, res);
  1.1021 +		lcr_dbf.close(dbh);
  1.1022 +		return -1;
  1.1023 +	    }
  1.1024 +	}
  1.1025 +	if (VAL_NULL(ROW_VALUES(row) + 2) == 1) {
  1.1026 +	    LM_ERR("Route grp_id is NULL\n");
  1.1027 +	    lcr_dbf.free_result(dbh, res);
  1.1028 +	    lcr_dbf.close(dbh);
  1.1029 +	    return -1;
  1.1030 +	}
  1.1031 +	grp_id = (unsigned int)VAL_INT(ROW_VALUES(row) + 2);
  1.1032 +	if (VAL_NULL(ROW_VALUES(row) + 3) == 1) {
  1.1033 +	    LM_ERR("Route priority is NULL\n");
  1.1034 +	    lcr_dbf.free_result(dbh, res);
  1.1035 +	    lcr_dbf.close(dbh);
  1.1036 +	    return -1;
  1.1037 +	}
  1.1038 +	priority = (unsigned int)VAL_INT(ROW_VALUES(row) + 3);
  1.1039 +
  1.1040 +	if (*lcrs == lcrs_1) {
  1.1041 +	    lcrs_2[i].prefix_len = prefix_len;
  1.1042 +	    if (prefix_len)
  1.1043 +		memcpy(&(lcrs_2[i].prefix[0]), prefix, prefix_len);
  1.1044 +	    lcrs_2[i].from_uri_len = from_uri_len;
  1.1045 +	    if (from_uri_len) {
  1.1046 +		memcpy(&(lcrs_2[i].from_uri[0]), from_uri, from_uri_len);
  1.1047 +		lcrs_2[i].from_uri[from_uri_len] = '\0';
  1.1048 +	    }
  1.1049 +	    lcrs_2[i].grp_id = grp_id;
  1.1050 +	    lcrs_2[i].priority = priority;
  1.1051 +	    lcrs_2[i].end_record = 0;
  1.1052 +	} else {
  1.1053 +	    lcrs_1[i].prefix_len = prefix_len;
  1.1054 +	    if (prefix_len)
  1.1055 +		memcpy(&(lcrs_1[i].prefix[0]), prefix, prefix_len);
  1.1056 +	    lcrs_1[i].from_uri_len = from_uri_len;
  1.1057 +	    if (from_uri_len) {
  1.1058 +		memcpy(&(lcrs_1[i].from_uri[0]), from_uri, from_uri_len);
  1.1059 +		lcrs_1[i].from_uri[from_uri_len] = '\0';
  1.1060 +	    }
  1.1061 +	    lcrs_1[i].grp_id = grp_id;
  1.1062 +	    lcrs_1[i].priority = priority;
  1.1063 +	    lcrs_1[i].end_record = 0;
  1.1064 +	}
  1.1065 +    }
  1.1066 +
  1.1067 +    lcr_dbf.free_result(dbh, res);
  1.1068 +    lcr_dbf.close(dbh);
  1.1069 +
  1.1070 +    if (*lcrs == lcrs_1) {
  1.1071 +	lcrs_2[i].end_record = 1;
  1.1072 +	*lcrs = lcrs_2;
  1.1073 +    } else {
  1.1074 +	lcrs_1[i].end_record = 1;
  1.1075 +	*lcrs = lcrs_1;
  1.1076 +    }
  1.1077 +
  1.1078 +    (*lcrs_ws_reload_counter)++;
  1.1079 +    if (0 != load_all_regex()) {
  1.1080 +
  1.1081 +	return -1;
  1.1082 +    }
  1.1083 +
  1.1084 +    return 1;
  1.1085 +}
  1.1086 +
  1.1087 +
  1.1088 +int mi_print_gws(struct mi_node* rpl)
  1.1089 +{
  1.1090 +    unsigned int i;
  1.1091 +    struct mi_attr* attr;
  1.1092 +    uri_transport transport;
  1.1093 +    char *transp;
  1.1094 +    struct mi_node* node;
  1.1095 +    struct ip_addr address;
  1.1096 +    char* p;
  1.1097 +    int len;
  1.1098 +
  1.1099 +    for (i = 0; i < MAX_NO_OF_GWS; i++) {
  1.1100 +
  1.1101 +	if ((*gws)[i].ip_addr == 0) 
  1.1102 +	    break;
  1.1103 +
  1.1104 +	node= add_mi_node_child(rpl,0 ,"GW", 2, 0, 0);
  1.1105 +	if(node == NULL)
  1.1106 +	    return -1;
  1.1107 +
  1.1108 +	p = int2str((unsigned long)(*gws)[i].grp_id, &len );
  1.1109 +	attr = add_mi_attr(node, MI_DUP_VALUE, "GRP_ID", 6, p, len );
  1.1110 +	if(attr == NULL)
  1.1111 +	    return -1;
  1.1112 +
  1.1113 +	transport = (*gws)[i].transport;
  1.1114 +	if (transport == PROTO_UDP)
  1.1115 +	    transp= ";transport=udp";
  1.1116 +	else  if (transport == PROTO_TCP)
  1.1117 +	    transp= ";transport=tcp";
  1.1118 +	else  if (transport == PROTO_TLS)
  1.1119 +	    transp= ";transport=tls";
  1.1120 +	else
  1.1121 +	    transp= "";
  1.1122 +
  1.1123 +	address.af = AF_INET;
  1.1124 +	address.len = 4;
  1.1125 +	address.u.addr32[0] = (*gws)[i].ip_addr;
  1.1126 +	attr= addf_mi_attr(node,0 ,"URI", 3,"%s:%s:%d%s",
  1.1127 +			   ((*gws)[i].scheme == SIP_URI_T)?"sip":"sips",
  1.1128 +			   ip_addr2a(&address),
  1.1129 +			   ((*gws)[i].port == 0)?5060:(*gws)[i].port,transp);
  1.1130 +	if(attr == NULL)
  1.1131 +	    return -1;
  1.1132 +
  1.1133 +	p = int2str((unsigned long)(*gws)[i].strip, &len );
  1.1134 +	attr = add_mi_attr(node, MI_DUP_VALUE, "STRIP", 5, p, len);
  1.1135 +	if(attr == NULL)
  1.1136 +	    return -1;
  1.1137 +
  1.1138 +	attr = add_mi_attr(node, MI_DUP_VALUE, "TAG", 3,
  1.1139 +			   (*gws)[i].tag, (*gws)[i].tag_len );
  1.1140 +	if(attr == NULL)
  1.1141 +	    return -1;
  1.1142 +
  1.1143 +	p = int2str((unsigned long)(*gws)[i].flags, &len );
  1.1144 +	attr = add_mi_attr(node, MI_DUP_VALUE, "FLAGS", 5, p, len);
  1.1145 +	if(attr == NULL)
  1.1146 +	    return -1;
  1.1147 +    }
  1.1148 +
  1.1149 +    for (i = 0; i < MAX_NO_OF_LCRS; i++) {
  1.1150 +	if ((*lcrs)[i].end_record != 0)
  1.1151 +	    break;
  1.1152 +
  1.1153 +	node= add_mi_node_child(rpl, 0, "RULE", 4, 0, 0);
  1.1154 +	attr = add_mi_attr(node, 0, "PREFIX", 6, (*lcrs)[i].prefix,
  1.1155 +			   (*lcrs)[i].prefix_len );
  1.1156 +	if(attr== 0)
  1.1157 +	    return -1;
  1.1158 +
  1.1159 +	attr = add_mi_attr(node, 0, "FROM_URI", 8, (*lcrs)[i].from_uri,
  1.1160 +			   (*lcrs)[i].from_uri_len );
  1.1161 +	if(attr== 0)
  1.1162 +	    return -1;
  1.1163 +	
  1.1164 +	p = int2str((unsigned long)(*lcrs)[i].grp_id, &len );
  1.1165 +	attr = add_mi_attr(node, MI_DUP_VALUE, "GRP_ID", 6, p, len );
  1.1166 +	if(attr == NULL)
  1.1167 +	    return -1;
  1.1168 +
  1.1169 +	p = int2str((unsigned long)(*lcrs)[i].priority, &len );
  1.1170 +	attr = add_mi_attr(node, MI_DUP_VALUE, "PRIORITY", 8, p, len );
  1.1171 +	if(attr == NULL)
  1.1172 +	    return -1;
  1.1173 +
  1.1174 +    }
  1.1175 +
  1.1176 +    return 0;
  1.1177 +}
  1.1178 +
  1.1179 +
  1.1180 +/*
  1.1181 + * Load info of matching GWs from database to gw_uri AVPs
  1.1182 + */
  1.1183 +static int do_load_gws(struct sip_msg* _m, str *_from_uri, int _grp_id)
  1.1184 +{
  1.1185 +    str ruri_user, from_uri, value;
  1.1186 +    char from_uri_str[MAX_FROM_URI_LEN + 1];
  1.1187 +    char ruri[MAX_URI_SIZE];
  1.1188 +    unsigned int i, j, k, index, addr, port, strip, gw_index,
  1.1189 +	duplicated_gw, flags, have_rpid_avp;
  1.1190 +    uri_type scheme;
  1.1191 +    uri_transport transport;
  1.1192 +    struct ip_addr address;
  1.1193 +    str addr_str, port_str;
  1.1194 +    char *at, *tag, *strip_string, *flags_string;
  1.1195 +    struct usr_avp *avp;
  1.1196 +    int_str val;
  1.1197 +    struct mi matched_gws[MAX_NO_OF_GWS + 1];
  1.1198 +    unsigned short tag_len, prefix_len, priority;
  1.1199 +    int randomizer_start, randomizer_end, randomizer_flag,
  1.1200 +	strip_len, flags_len;
  1.1201 +    struct lcr_info lcr_rec;
  1.1202 +
  1.1203 +	/* Find Request-URI user */
  1.1204 +	if ((parse_sip_msg_uri(_m) < 0) || (!_m->parsed_uri.user.s)) {
  1.1205 +		LM_ERR("Error while parsing R-URI\n");
  1.1206 +		return -1;
  1.1207 +	}
  1.1208 +	ruri_user = _m->parsed_uri.user;
  1.1209 +
  1.1210 +    if (_from_uri) {
  1.1211 +	/* take caller uri from _from_uri argument */
  1.1212 +	from_uri = *_from_uri;
  1.1213 +    } else {
  1.1214 +	/* take caller uri from RPID or From URI */
  1.1215 +	have_rpid_avp = 0;
  1.1216 +	avp = search_first_avp(rpid_avp_type, rpid_avp, &val, 0);
  1.1217 +	if (avp != NULL) {
  1.1218 +	    /* Get URI user from RPID if not empty */
  1.1219 +	    if (avp->flags & AVP_VAL_STR) {
  1.1220 +		if (val.s.s && val.s.len) {
  1.1221 +		    from_uri = val.s;
  1.1222 +		    have_rpid_avp = 1;
  1.1223 +		}
  1.1224 +	    } else {
  1.1225 +		from_uri.s = int2str(val.n, &from_uri.len);
  1.1226 +		have_rpid_avp = 1;
  1.1227 +	    }
  1.1228 +	}
  1.1229 +	if (!have_rpid_avp) {
  1.1230 +	    /* Get URI from From URI */
  1.1231 +	    if ((!_m->from) && (parse_headers(_m, HDR_FROM_F, 0) == -1)) {
  1.1232 +		LM_ERR("Error while parsing headers\n");
  1.1233 +		return -1;
  1.1234 +	    }
  1.1235 +	    if (!_m->from) {
  1.1236 +		LM_ERR("From header field not found\n");
  1.1237 +		return -1;
  1.1238 +	    }
  1.1239 +	    if ((!(_m->from)->parsed) && (parse_from_header(_m) < 0)) {
  1.1240 +		LM_ERR("Error while parsing From header\n");
  1.1241 +		return -1;
  1.1242 +	    }
  1.1243 +	    from_uri = get_from(_m)->uri;
  1.1244 +	}
  1.1245 +    }
  1.1246 +    if (from_uri.len <= MAX_FROM_URI_LEN) {
  1.1247 +	strncpy(from_uri_str, from_uri.s, from_uri.len);
  1.1248 +	from_uri_str[from_uri.len] = '\0';
  1.1249 +    } else {
  1.1250 +	LM_ERR("From URI is too long <%u>\n", from_uri.len);
  1.1251 +	return -1;
  1.1252 +    }
  1.1253 +
  1.1254 +    /*
  1.1255 +     * Check if the gws and lcrs were reloaded
  1.1256 +     */
  1.1257 +	if (reload_counter != *lcrs_ws_reload_counter) {
  1.1258 +		if (load_all_regex() != 0) {
  1.1259 +		    return -1;
  1.1260 +		}
  1.1261 +	}
  1.1262 +
  1.1263 +    /*
  1.1264 +     * Let's match the gws:
  1.1265 +     *  1. prefix matching
  1.1266 +     *  2. from_uri matching
  1.1267 +     *  3. _grp_id matching
  1.1268 +     *
  1.1269 +     * Note: A gateway must be in the list _only_ once.
  1.1270 +     */
  1.1271 +    gw_index = 0;
  1.1272 +    duplicated_gw = 0;
  1.1273 +    for (i = 0; i < MAX_NO_OF_LCRS; i++) {
  1.1274 +	lcr_rec = (*lcrs)[i];
  1.1275 +	if (lcr_rec.end_record != 0) {
  1.1276 +	    break;
  1.1277 +	}
  1.1278 +	if ( ((prefix_mode_param == 0) && (lcr_rec.prefix_len <= ruri_user.len) &&
  1.1279 +	      (strncmp(lcr_rec.prefix, ruri_user.s, lcr_rec.prefix_len)==0)) ||
  1.1280 +	     ( (prefix_mode_param != 0) && ( (lcr_rec.prefix_len == 0) ||
  1.1281 +					(prefix_reg[i].valid &&
  1.1282 +					 (regexec(&(prefix_reg[i].re), ruri_user.s, 0,
  1.1283 +						  (regmatch_t *)NULL, 0) == 0)) ) ) ) {
  1.1284 +	    /* 1. Prefix matching is done */
  1.1285 +	    if ((lcr_rec.from_uri_len == 0) ||
  1.1286 +		(from_uri_reg[i].valid &&
  1.1287 +		 (regexec(&(from_uri_reg[i].re), from_uri_str, 0,
  1.1288 +			  (regmatch_t *)NULL, 0) == 0))) {
  1.1289 +		/* 2. from_uri matching is done */
  1.1290 +		for (j = 0; j < MAX_NO_OF_GWS; j++) {
  1.1291 +		    if ((*gws)[j].ip_addr == 0) {
  1.1292 +			break;
  1.1293 +		    }
  1.1294 +		    if (lcr_rec.grp_id == (*gws)[j].grp_id &&
  1.1295 +			(_grp_id < 0 || (*gws)[j].grp_id == _grp_id)) {
  1.1296 +			/* 3. _grp_id matching is done */
  1.1297 +			for (k = 0; k < gw_index; k++) {
  1.1298 +			    if ((*gws)[j].ip_addr ==
  1.1299 +				(*gws)[matched_gws[k].gw_index].ip_addr) {
  1.1300 +				/* Found the same gw in the list  */
  1.1301 +				/* Let's keep the one with higher */
  1.1302 +				/* match on prefix len            */
  1.1303 +				LM_DBG("Duplicate gw for index"
  1.1304 +				       " %d [%d,%d] and current [%d,%d] \n",
  1.1305 +				       k, matched_gws[k].route_index,
  1.1306 +				       matched_gws[k].route_index, i, j);
  1.1307 +				duplicated_gw = 1;
  1.1308 +				if (lcr_rec.prefix_len >
  1.1309 +				    (*lcrs)[matched_gws[k].route_index].prefix_len) {
  1.1310 +				    /* Replace the old entry with the new one */
  1.1311 +				    LM_DBG("Replace [%d,%d]"
  1.1312 +					   " with [%d,%d] on index %d:"
  1.1313 +					   " prefix reason %d>%d\n",
  1.1314 +					   matched_gws[k].route_index,
  1.1315 +					   matched_gws[k].gw_index, i, j, k,
  1.1316 +					   lcr_rec.prefix_len,
  1.1317 +					   (*lcrs)[matched_gws[k].route_index].prefix_len);
  1.1318 +				    matched_gws[k].route_index = i;
  1.1319 +				    matched_gws[k].gw_index = j;
  1.1320 +				    /* Stop searching in the matched_gws list */
  1.1321 +				    break;
  1.1322 +				} else if (lcr_rec.prefix_len ==
  1.1323 +					   (*lcrs)[matched_gws[k].route_index].prefix_len) {
  1.1324 +				    if (lcr_rec.priority >
  1.1325 +					(*lcrs)[matched_gws[k].route_index].priority) {
  1.1326 +					/* Replace the old entry with the new one */
  1.1327 +					LM_DBG("Replace [%d,%d] with"
  1.1328 +					       " [%d,%d] on index %d:"
  1.1329 +					       " priority reason %d>%d\n",
  1.1330 +					       matched_gws[k].route_index,
  1.1331 +					       matched_gws[k].gw_index,
  1.1332 +					       i, j, k, lcr_rec.priority,
  1.1333 +					       (*lcrs)[matched_gws[k].route_index].priority);
  1.1334 +					matched_gws[k].route_index = i;
  1.1335 +					matched_gws[k].gw_index = j;
  1.1336 +					/* Stop searching in the matched_gws list */
  1.1337 +					break;
  1.1338 +				    }
  1.1339 +				}
  1.1340 +			    }
  1.1341 +			}
  1.1342 +			if (duplicated_gw == 0) {
  1.1343 +			    /* This is a new gw */
  1.1344 +			    matched_gws[gw_index].route_index = i;
  1.1345 +			    matched_gws[gw_index].gw_index = j;
  1.1346 +			    LM_DBG("Added matched_gws[%d]=[%d,%d]\n",
  1.1347 +				   gw_index, i, j);
  1.1348 +			    gw_index++;
  1.1349 +			} else {
  1.1350 +			    duplicated_gw = 0;
  1.1351 +			}
  1.1352 +		    }
  1.1353 +		}
  1.1354 +	    }
  1.1355 +	}
  1.1356 +    }
  1.1357 +    matched_gws[gw_index].route_index = -1;
  1.1358 +    matched_gws[gw_index].gw_index = -1;
  1.1359 +
  1.1360 +    /*
  1.1361 +     * Sort the gateways based on:
  1.1362 +     *  1. prefix len
  1.1363 +     *  2. priority
  1.1364 +     */
  1.1365 +    qsort(matched_gws, gw_index, sizeof(struct mi), comp_lcrs);
  1.1366 +	randomizer_start = 0;
  1.1367 +
  1.1368 +    /* Randomizing the gateways with same prefix_len and same priority */
  1.1369 +    randomizer_flag = 0;
  1.1370 +    prefix_len = (*lcrs)[matched_gws[0].route_index].prefix_len;
  1.1371 +    priority = (*lcrs)[matched_gws[0].route_index].priority;
  1.1372 +    for (i = 1; i < gw_index; i++) {
  1.1373 + 	if ( prefix_len == (*lcrs)[matched_gws[i].route_index].prefix_len &&
  1.1374 + 	     priority == (*lcrs)[matched_gws[i].route_index].priority) {
  1.1375 +	    /* we have a match */
  1.1376 +	    if (randomizer_flag == 0) {
  1.1377 +		randomizer_flag = 1;
  1.1378 +		randomizer_start = i - 1;
  1.1379 +	    }
  1.1380 +	    matched_gws[i - 1].randomizer = rand();
  1.1381 + 	}
  1.1382 +	else {
  1.1383 +	    if (randomizer_flag == 1) {
  1.1384 +		randomizer_end = i - 1;
  1.1385 +		randomizer_flag = 0;
  1.1386 +		qsort(&matched_gws[randomizer_start],
  1.1387 +		      randomizer_end - randomizer_start + 1,
  1.1388 +		      sizeof(struct mi), rand_lcrs);
  1.1389 +	    }
  1.1390 +	    prefix_len = (*lcrs)[matched_gws[i].route_index].prefix_len;
  1.1391 +	    priority = (*lcrs)[matched_gws[i].route_index].priority;
  1.1392 +	}
  1.1393 +    }
  1.1394 +    if (randomizer_flag == 1) {
  1.1395 +	randomizer_end = gw_index - 1;
  1.1396 +	matched_gws[i - 1].randomizer = rand();
  1.1397 +	qsort(&matched_gws[randomizer_start],
  1.1398 +	      randomizer_end - randomizer_start + 1,
  1.1399 +	      sizeof(struct mi), rand_lcrs);
  1.1400 +    }
  1.1401 +
  1.1402 +    for (i = 0; i < MAX_NO_OF_GWS; i++) {
  1.1403 +	index = matched_gws[i].gw_index;
  1.1404 +	if (index == -1) {
  1.1405 +	    break;
  1.1406 +	}
  1.1407 +      	addr = (*gws)[index].ip_addr;
  1.1408 +	port = (*gws)[index].port;
  1.1409 +	scheme = (*gws)[index].scheme;
  1.1410 +	transport = (*gws)[index].transport;
  1.1411 +	flags = (*gws)[index].flags;
  1.1412 +	strip = (*gws)[index].strip;
  1.1413 +	if (strip > ruri_user.len) {
  1.1414 +	    LM_ERR("Strip count of gw is too large <%u>\n", strip);
  1.1415 +	    goto skip;
  1.1416 +	}
  1.1417 +	tag_len = (*gws)[index].tag_len;
  1.1418 +	tag = (*gws)[index].tag;
  1.1419 +	if (6 + tag_len + 40 /* flags + strip */ + 1 + 15 + 1 + 5 + 1 + 14 >
  1.1420 +	    MAX_URI_SIZE) {
  1.1421 +	    LM_ERR("Request URI would be too long\n");
  1.1422 +	    goto skip;
  1.1423 +	}
  1.1424 +	at = (char *)&(ruri[0]);
  1.1425 +	flags_string = int2str(flags, &flags_len);
  1.1426 +	memcpy(at, flags_string, flags_len);
  1.1427 +	at = at + flags_len;
  1.1428 +	if (scheme == SIP_URI_T) {
  1.1429 +	    memcpy(at, "sip:", 4); at = at + 4;
  1.1430 +	} else if (scheme == SIPS_URI_T) {
  1.1431 +	    memcpy(at, "sips:", 5); at = at + 5;
  1.1432 +	} else {
  1.1433 +	    LM_ERR("Unknown or unsupported URI scheme <%u>\n",
  1.1434 +		   (unsigned int)scheme);
  1.1435 +	    goto skip;
  1.1436 +	}
  1.1437 +	if (tag_len) {
  1.1438 +	    memcpy(at, tag, tag_len); at = at + tag_len;
  1.1439 +	}
  1.1440 +	/* Add strip in this form |number.
  1.1441 +	 * For example: |3 means strip first 3 characters.
  1.1442 +         */
  1.1443 +	*at = '|'; at = at + 1;
  1.1444 +	strip_string = int2str(strip, &strip_len);
  1.1445 +	memcpy(at, strip_string, strip_len);
  1.1446 +	at = at + strip_len;
  1.1447 +	*at = '@'; at = at + 1;
  1.1448 +	address.af = AF_INET;
  1.1449 +	address.len = 4;
  1.1450 +	address.u.addr32[0] = addr;
  1.1451 +	addr_str.s = ip_addr2a(&address);
  1.1452 +	addr_str.len = strlen(addr_str.s);
  1.1453 +	memcpy(at, addr_str.s, addr_str.len); at = at + addr_str.len;
  1.1454 +	if (port != 0) {
  1.1455 +	    if (port > 65536) {
  1.1456 +		LM_ERR("Port of GW is too large <%u>\n", port);
  1.1457 +		goto skip;
  1.1458 +	    }
  1.1459 +	    *at = ':'; at = at + 1;
  1.1460 +	    port_str.s = int2str(port, &port_str.len);
  1.1461 +	    memcpy(at, port_str.s, port_str.len); at = at + port_str.len;
  1.1462 +	}
  1.1463 +	if (transport != PROTO_NONE) {
  1.1464 +	    memcpy(at, ";transport=", 11); at = at + 11;
  1.1465 +	    if (transport == PROTO_UDP) {
  1.1466 +		memcpy(at, "udp", 3); at = at + 3;
  1.1467 +	    } else if (transport == PROTO_TCP) {
  1.1468 +		memcpy(at, "tcp", 3); at = at + 3;
  1.1469 +	    } else if (transport == PROTO_TLS) {
  1.1470 +		memcpy(at, "tls", 3); at = at + 3;
  1.1471 +	    } else {
  1.1472 +		LM_ERR("Unknown or unsupported transport <%u>\n",
  1.1473 +		       (unsigned int)transport);
  1.1474 +		goto skip;
  1.1475 +	    }
  1.1476 +	}
  1.1477 +	value.s = (char *)&(ruri[0]);
  1.1478 +	value.len = at - value.s;
  1.1479 +	val.s = value;
  1.1480 +	add_avp(gw_uri_avp_type|AVP_VAL_STR, gw_uri_avp, val);
  1.1481 +	LM_DBG("Added gw_uri_avp <%.*s>\n", value.len, value.s);
  1.1482 +    skip:
  1.1483 +	continue;
  1.1484 +    }
  1.1485 +
  1.1486 +    return 1;
  1.1487 +}
  1.1488 +
  1.1489 +/*
  1.1490 + * Load info of matching GWs from database to gw_uri AVPs
  1.1491 + * taking into account the given group id.  Caller URI is taken
  1.1492 + * from request.
  1.1493 + */
  1.1494 +static int load_gws_from_grp(struct sip_msg* _m, char* _s1, char* _s2)
  1.1495 +{
  1.1496 +	str grp_s;
  1.1497 +	unsigned int grp_id;
  1.1498 +	
  1.1499 +	if(((pv_elem_p)_s1)->spec.getf!=NULL)
  1.1500 +	{
  1.1501 +		if(pv_printf_s(_m, (pv_elem_p)_s1, &grp_s)!=0)
  1.1502 +			return -1;
  1.1503 +		if(str2int(&grp_s, &grp_id)!=0)
  1.1504 +			return -1;
  1.1505 +	} else {
  1.1506 +		grp_id = ((pv_elem_p)_s1)->spec.pvp.pvn.u.isname.name.n;
  1.1507 +	}
  1.1508 +	if (grp_id > 0) return do_load_gws(_m, (str *)0, (int)grp_id);
  1.1509 +	else return -1;
  1.1510 +}
  1.1511 +
  1.1512 +
  1.1513 +/*
  1.1514 + * Load info of matching GWs from database to gw_uri AVPs.
  1.1515 + * Caller URI is taken from request.
  1.1516 + */
  1.1517 +static int load_gws_0(struct sip_msg* _m, char* _s1, char* _s2)
  1.1518 +{
  1.1519 +    return do_load_gws(_m, (str *)0, -1);
  1.1520 +}
  1.1521 +
  1.1522 +
  1.1523 +/*
  1.1524 + * Load info of matching GWs from database to gw_uri AVPs.
  1.1525 + * Caller URI is taken from pseudo variable argument.
  1.1526 + */
  1.1527 +static int load_gws_1(struct sip_msg* _m, char* _sp, char* _s2)
  1.1528 +{
  1.1529 +    pv_spec_t *sp;
  1.1530 +    pv_value_t pv_val;
  1.1531 +    sp = (pv_spec_t *)_sp;
  1.1532 +
  1.1533 +    if (sp && (pv_get_spec_value(_m, sp, &pv_val) == 0)) {
  1.1534 +	if (pv_val.flags & PV_VAL_STR) {
  1.1535 +	    if (pv_val.rs.len == 0 || pv_val.rs.s == NULL) {
  1.1536 +		LM_DBG("missing from uri\n");
  1.1537 +		return -1;
  1.1538 +	    }
  1.1539 + 	    return do_load_gws(_m, &(pv_val.rs), -1);
  1.1540 +	} else {
  1.1541 +	   LM_DBG("pseudo variable value is not string\n");
  1.1542 +	   return -1;
  1.1543 +	}
  1.1544 +    } else {
  1.1545 +	LM_DBG("cannot get pseudo variable value\n");
  1.1546 +	return -1;
  1.1547 +    }
  1.1548 +}
  1.1549 +
  1.1550 +
  1.1551 +/*
  1.1552 + * Rewrites scheme, host, port, and transport parts of R-URI based on first 
  1.1553 + * gw_uri AVP value, which is then destroyed.  Also saves R-URI user to 
  1.1554 + * ruri_user AVP for later use in failure route block.
  1.1555 + * If called from failure route block, appends a new branch to request
  1.1556 + * where scheme, host, port, and transport of URI are taken from the first
  1.1557 + * gw_uri AVP value, which is then destroyed.  URI user is taken from
  1.1558 + * ruri_user AVP value saved earlier.
  1.1559 + * Returns 1 upon success and -1 upon failure.
  1.1560 + */
  1.1561 +static int next_gw(struct sip_msg* _m, char* _s1, char* _s2)
  1.1562 +{
  1.1563 +    int_str gw_uri_val, ruri_user_val, val;
  1.1564 +    struct usr_avp *gu_avp, *ru_avp;
  1.1565 +    int rval;
  1.1566 +    str new_ruri;
  1.1567 +    char *at, *at_char, *strip_char, *endptr;
  1.1568 +    unsigned int strip;
  1.1569 +
  1.1570 +    gu_avp = search_first_avp(gw_uri_avp_type, gw_uri_avp, &gw_uri_val, 0);
  1.1571 +    if (!gu_avp) return -1;
  1.1572 +
  1.1573 +    /* Set flags_avp from integer at the beginning of of gw_uri */
  1.1574 +    val.n = (int)strtoul(gw_uri_val.s.s, &at, 0);
  1.1575 +    add_avp(flags_avp_type, flags_avp, val);
  1.1576 +    LM_DBG("Added flags_avp <%u>\n", (unsigned int)val.n);
  1.1577 +
  1.1578 +    gw_uri_val.s.len = gw_uri_val.s.len - (at - gw_uri_val.s.s);
  1.1579 +    gw_uri_val.s.s = at;
  1.1580 +
  1.1581 +	/* Create new Request-URI taking URI user from ruri_user AVP
  1.1582 +	   and other parts of from gateway URI AVP. */
  1.1583 +	ru_avp = search_first_avp(ruri_user_avp_type, ruri_user_avp,
  1.1584 +		&ruri_user_val, 0);
  1.1585 +	if (!ru_avp) {
  1.1586 +		LM_DBG("ruri_user AVP no yet set -> use RURI\n");
  1.1587 +		/* parse RURI and ger username */
  1.1588 +		if (parse_sip_msg_uri(_m) < 0) {
  1.1589 +			LM_ERR("Parsing of R-URI failed\n");
  1.1590 +			return -1;
  1.1591 +		}
  1.1592 +		ruri_user_val.s = _m->parsed_uri.user;
  1.1593 +		/* Save Request-URI user for use in FAILURE_ROUTE */
  1.1594 +		val.s = _m->parsed_uri.user;
  1.1595 +		add_avp(ruri_user_avp_type|AVP_VAL_STR, ruri_user_avp, val);
  1.1596 +		LM_DBG("Added ruri_user_avp <%.*s>\n", val.s.len, val.s.s);
  1.1597 +	}
  1.1598 +
  1.1599 +	new_ruri.s = pkg_malloc(gw_uri_val.s.len + ruri_user_val.s.len);
  1.1600 +	if (!new_ruri.s) {
  1.1601 +	    LM_ERR("No memory for new R-URI.\n");
  1.1602 +	    return -1;
  1.1603 +	}
  1.1604 +	at_char = memchr(gw_uri_val.s.s, '@', gw_uri_val.s.len);
  1.1605 +	if (!at_char) {
  1.1606 +	    pkg_free(new_ruri.s);
  1.1607 +	    LM_ERR("No @ in gateway URI <%.*s>\n",
  1.1608 +		   gw_uri_val.s.len, gw_uri_val.s.s);
  1.1609 +	    return -1;
  1.1610 +	}
  1.1611 +	strip_char = memchr(gw_uri_val.s.s, '|', gw_uri_val.s.len);
  1.1612 +	if (!strip_char || strip_char + 1 >= at_char) {
  1.1613 +	    pkg_free(new_ruri.s);
  1.1614 +	    LM_ERR("No strip char | and at least one "
  1.1615 +		   "char before @ in gateway URI <%.*s>\n",
  1.1616 +		   gw_uri_val.s.len, gw_uri_val.s.s);
  1.1617 +	    return -1;
  1.1618 +	}
  1.1619 +	at = new_ruri.s;
  1.1620 +	memcpy(at, gw_uri_val.s.s, strip_char - gw_uri_val.s.s);
  1.1621 +	at = at + (strip_char - gw_uri_val.s.s);
  1.1622 +	strip = strtol(strip_char + 1, &endptr, 10);
  1.1623 +	if (endptr != at_char) {
  1.1624 +	    pkg_free(new_ruri.s);
  1.1625 +	    LM_ERR("Non-digit char between | and @ chars in gw URI <%.*s>\n",
  1.1626 +		   gw_uri_val.s.len, gw_uri_val.s.s);
  1.1627 +	    return -1;
  1.1628 +	}
  1.1629 +	if (ruri_user_val.s.len - strip > 0) {
  1.1630 +	    memcpy(at, ruri_user_val.s.s + strip,
  1.1631 +		   ruri_user_val.s.len - strip);
  1.1632 +	    at = at + ruri_user_val.s.len - strip;
  1.1633 +	}
  1.1634 +	if (*(at - 1) != ':') {
  1.1635 +	    memcpy(at, at_char, gw_uri_val.s.len - (at_char - gw_uri_val.s.s));
  1.1636 +	    at = at + gw_uri_val.s.len - (at_char - gw_uri_val.s.s);
  1.1637 +	} else {
  1.1638 +	    memcpy(at, at_char + 1, gw_uri_val.s.len -
  1.1639 +		   (at_char + 1 - gw_uri_val.s.s));
  1.1640 +	    at = at + gw_uri_val.s.len - (at_char + 1 - gw_uri_val.s.s);
  1.1641 +	}
  1.1642 +	new_ruri.len = at - new_ruri.s;
  1.1643 +
  1.1644 +	/* set new RURI */
  1.1645 +	rval = set_ruri( _m, &new_ruri);
  1.1646 +	pkg_free(new_ruri.s);
  1.1647 +	destroy_avp(gu_avp);
  1.1648 +	if (rval!=0) {
  1.1649 +		LM_ERR("failed to set new RURI\n");
  1.1650 +		return -1;
  1.1651 +	}
  1.1652 +
  1.1653 +	return 1;
  1.1654 +}
  1.1655 +
  1.1656 +
  1.1657 +/*
  1.1658 + * Checks if request comes from a gateway
  1.1659 + */
  1.1660 +static int do_from_gw(struct sip_msg* _m, pv_spec_t *addr_sp, int grp_id)
  1.1661 +{
  1.1662 +    int i;
  1.1663 +    unsigned int src_addr;
  1.1664 +    pv_value_t pv_val;
  1.1665 +    struct ip_addr *ip;
  1.1666 +    int_str val;
  1.1667 +
  1.1668 +	if (addr_sp && (pv_get_spec_value(_m, addr_sp, &pv_val) == 0)) {
  1.1669 +		if (pv_val.flags & PV_VAL_INT) {
  1.1670 +			src_addr = pv_val.ri;
  1.1671 +		} else if (pv_val.flags & PV_VAL_STR) {
  1.1672 +			if ( (ip=str2ip( &pv_val.rs)) == NULL) {
  1.1673 +				LM_ERR("failed to convert IP address string to in_addr\n");
  1.1674 +				return -1;
  1.1675 +			} else {
  1.1676 +				src_addr = ip->u.addr32[0];
  1.1677 +			}
  1.1678 +		} else {
  1.1679 +			LM_ERR("IP address PV empty value\n");
  1.1680 +			return -1;
  1.1681 +		}
  1.1682 +	} else {
  1.1683 +		src_addr = _m->rcv.src_ip.u.addr32[0];
  1.1684 +	}
  1.1685 +
  1.1686 +    for (i = 0; i < MAX_NO_OF_GWS; i++) {
  1.1687 +	if ((*gws)[i].ip_addr == 0) {
  1.1688 +	    return -1;
  1.1689 +	}
  1.1690 +	if ((*gws)[i].ip_addr == src_addr && 
  1.1691 +	    (grp_id < 0 || (*gws)[i].grp_id == grp_id)) {
  1.1692 +	    LM_DBG("Request came from gw\n");
  1.1693 +	    val.n = (int)(*gws)[i].flags;
  1.1694 +	    add_avp(flags_avp_type, flags_avp, val);
  1.1695 +	    LM_DBG("Added flags_avp <%u>\n", (unsigned int)val.n);
  1.1696 +	    return 1;
  1.1697 +	}
  1.1698 +    }
  1.1699 +
  1.1700 +    LM_DBG("Request did not come from gw\n");
  1.1701 +    return -1;
  1.1702 +}
  1.1703 +
  1.1704 +
  1.1705 +/*
  1.1706 + * Checks if request comes from a gateway, taking source address from request
  1.1707 + * and taking into account the group id.
  1.1708 + */
  1.1709 +static int from_gw_grp(struct sip_msg* _m, char* _grp_id, char* _s2)
  1.1710 +{
  1.1711 +    return do_from_gw(_m, (pv_spec_t *)0, (int)(long)_grp_id);
  1.1712 +}
  1.1713 +
  1.1714 +
  1.1715 +/*
  1.1716 + * Checks if request comes from a gateway, taking src_address from request
  1.1717 + * and ignoring group id.
  1.1718 + */
  1.1719 +static int from_gw_0(struct sip_msg* _m, char* _s1, char* _s2)
  1.1720 +{
  1.1721 +    return do_from_gw(_m, (pv_spec_t *)0, -1);
  1.1722 +}
  1.1723 +
  1.1724 +
  1.1725 +/*
  1.1726 + * Checks if request comes from a gateway, taking source address from pw
  1.1727 + * and ignoring group id.
  1.1728 + */
  1.1729 +static int from_gw_1(struct sip_msg* _m, char* _addr_sp, char* _s2)
  1.1730 +{
  1.1731 +    return do_from_gw(_m, (pv_spec_t *)_addr_sp, -1);
  1.1732 +}
  1.1733 +
  1.1734 +
  1.1735 +/*
  1.1736 + * Checks if in-dialog request goes to gateway
  1.1737 + */
  1.1738 +static int do_to_gw(struct sip_msg* _m, int grp_id)
  1.1739 +{
  1.1740 +    char host[16];
  1.1741 +    struct in_addr addr;
  1.1742 +    unsigned int i;
  1.1743 +
  1.1744 +    if((_m->parsed_uri_ok == 0) && (parse_sip_msg_uri(_m) < 0)) {
  1.1745 +	LM_ERR("Error while parsing the R-URI\n");
  1.1746 +	return -1;
  1.1747 +    }
  1.1748 +
  1.1749 +    if (_m->parsed_uri.host.len > 15) {
  1.1750 +	return -1;
  1.1751 +    }
  1.1752 +    memcpy(host, _m->parsed_uri.host.s, _m->parsed_uri.host.len);
  1.1753 +    host[_m->parsed_uri.host.len] = 0;
  1.1754 +
  1.1755 +    if (!inet_aton(host, &addr)) {
  1.1756 +	return -1;
  1.1757 +    }
  1.1758 +
  1.1759 +    for (i = 0; i < MAX_NO_OF_GWS; i++) {
  1.1760 +	if ((*gws)[i].ip_addr == 0) {
  1.1761 +	    return -1;
  1.1762 +	}
  1.1763 +	if ((*gws)[i].ip_addr == addr.s_addr && 
  1.1764 +		(grp_id < 0 || (*gws)[i].grp_id == grp_id)) {
  1.1765 +	    return 1;
  1.1766 +	}
  1.1767 +    }
  1.1768 +
  1.1769 +    return -1;
  1.1770 +}
  1.1771 +
  1.1772 +
  1.1773 +/*
  1.1774 + * Checks if in-dialog request goes to gateway, taking
  1.1775 + * into account the group id.
  1.1776 + */
  1.1777 +static int to_gw_grp(struct sip_msg* _m, char* _s1, char* _s2)
  1.1778 +{
  1.1779 +    int grp_id;
  1.1780 +
  1.1781 +    grp_id = (int)(long)_s1;
  1.1782 +    return do_to_gw(_m, grp_id);
  1.1783 +}
  1.1784 +
  1.1785 +
  1.1786 +/*
  1.1787 + * Checks if in-dialog request goes to gateway, ignoring
  1.1788 + * the group id.
  1.1789 + */
  1.1790 +static int to_gw(struct sip_msg* _m, char* _s1, char* _s2)
  1.1791 +{
  1.1792 +    return do_to_gw(_m, -1);
  1.1793 +}
  1.1794 +
  1.1795 +
  1.1796 +/* 
  1.1797 + * Frees contact list used by load_contacts function
  1.1798 + */
  1.1799 +static inline void free_contact_list(struct contact *curr) {
  1.1800 +    struct contact *prev;
  1.1801 +    while (curr) {
  1.1802 +	prev = curr;
  1.1803 +	curr = curr->next;
  1.1804 +	pkg_free(prev);
  1.1805 +    }
  1.1806 +}
  1.1807 +
  1.1808 +/* Encode branch info from contact struct to str */
  1.1809 +static inline int encode_branch_info(str *info, struct contact *con)
  1.1810 +{
  1.1811 +    char *at, *s;
  1.1812 +    int len;
  1.1813 +
  1.1814 +    info->len = con->uri.len + con->dst_uri.len +
  1.1815 +	con->path.len + MAX_SOCKET_STR + INT2STR_MAX_LEN + 5;
  1.1816 +    info->s = pkg_malloc(info->len);
  1.1817 +    if (!info->s) {
  1.1818 +	LM_ERR("No memory left for branch info\n");
  1.1819 +	return 0;
  1.1820 +    }
  1.1821 +    at = info->s;
  1.1822 +    memcpy(at, con->uri.s, con->uri.len);
  1.1823 +    at = at + con->uri.len;
  1.1824 +    *at = '\n';
  1.1825 +    at++;
  1.1826 +    memcpy(at, con->dst_uri.s, con->dst_uri.len);
  1.1827 +    at = at + con->dst_uri.len;
  1.1828 +    *at = '\n';
  1.1829 +    at++;
  1.1830 +    memcpy(at, con->path.s, con->path.len);
  1.1831 +    at = at + con->path.len;
  1.1832 +    *at = '\n';
  1.1833 +    at++;
  1.1834 +    if (con->sock) {
  1.1835 +	len = MAX_SOCKET_STR;
  1.1836 +	if (!socket2str(con->sock, at, &len, 1)) {
  1.1837 +	    LM_ERR("Failed to convert socket to str\n");
  1.1838 +	    return 0;
  1.1839 +	}
  1.1840 +    } else {
  1.1841 +	len = 0;
  1.1842 +    }
  1.1843 +    at = at + len;
  1.1844 +    *at = '\n';
  1.1845 +    at++;
  1.1846 +    s = int2str(con->flags, &len);
  1.1847 +    memcpy(at, s, len);
  1.1848 +    at = at + len;
  1.1849 +    *at = '\n';
  1.1850 +    info->len = at - info->s + 1;
  1.1851 +
  1.1852 +    return 1;
  1.1853 +}
  1.1854 +
  1.1855 +
  1.1856 +/* Encode branch info from str */
  1.1857 +static inline int decode_branch_info(char *info, str *uri, str *dst, str *path,
  1.1858 +			      struct socket_info **sock, unsigned int *flags)
  1.1859 +{
  1.1860 +    str s, host;
  1.1861 +    int port, proto;
  1.1862 +    char *pos, *at;
  1.1863 +
  1.1864 +    pos = strchr(info, '\n');
  1.1865 +    uri->len = pos - info;
  1.1866 +    if (uri->len) {
  1.1867 +	uri->s = info;
  1.1868 +    } else {
  1.1869 +	uri->s = 0;
  1.1870 +    }
  1.1871 +    at = pos + 1;
  1.1872 +
  1.1873 +    pos = strchr(at, '\n');
  1.1874 +    dst->len = pos - at;
  1.1875 +    if (dst->len) {
  1.1876 +	dst->s = at;
  1.1877 +    } else {
  1.1878 +	dst->s = 0;
  1.1879 +    }
  1.1880 +    at = pos + 1;
  1.1881 +
  1.1882 +    pos = strchr(at, '\n');
  1.1883 +    path->len = pos - at;
  1.1884 +    if (path->len) {
  1.1885 +	path->s = at;
  1.1886 +    } else {
  1.1887 +	path->s = 0;
  1.1888 +    }
  1.1889 +    at = pos + 1;
  1.1890 +
  1.1891 +    pos = strchr(at, '\n');
  1.1892 +    s.len = pos - at;
  1.1893 +    if (s.len) {
  1.1894 +	s.s = at;
  1.1895 +	if (parse_phostport(s.s, s.len, &host.s, &host.len,
  1.1896 +			    &port, &proto) != 0) {
  1.1897 +	    LM_ERR("Parsing of socket info <%.*s> failed\n",  s.len, s.s);
  1.1898 +	    return 0;
  1.1899 +	}
  1.1900 +	*sock = grep_sock_info(&host, (unsigned short)port,
  1.1901 +			       (unsigned short)proto);
  1.1902 +	if (*sock == 0) {
  1.1903 +	    LM_ERR("Invalid socket <%.*s>\n", s.len, s.s);
  1.1904 +	    return 0;
  1.1905 +	}
  1.1906 +    } else {
  1.1907 +	*sock = 0;
  1.1908 +    }
  1.1909 +    at = pos + 1;
  1.1910 +
  1.1911 +    pos = strchr(at, '\n');
  1.1912 +    s.len = pos - at;
  1.1913 +    if (s.len) {
  1.1914 +	s.s = at;
  1.1915 +	if (str2int(&s, flags) != 0) {
  1.1916 +	    LM_ERR("Failed to decode flags <%.*s>\n", s.len, s.s);
  1.1917 +	    return 0;
  1.1918 +	}
  1.1919 +    } else {
  1.1920 +	*flags = 0;
  1.1921 +    }
  1.1922 +
  1.1923 +    return 1;
  1.1924 +}
  1.1925 +
  1.1926 +
  1.1927 +/* 
  1.1928 + * Loads contacts in destination set into "lcr_contact" AVP in reverse
  1.1929 + * priority order and associated each contact with Q_FLAG telling if
  1.1930 + * contact is the last one in its priority class.  Finally, removes
  1.1931 + * all branches from destination set.
  1.1932 + */
  1.1933 +static int load_contacts(struct sip_msg* msg, char* key, char* value)
  1.1934 +{
  1.1935 +    str uri, dst_uri, path, branch_info, *ruri;
  1.1936 +    qvalue_t q, ruri_q;
  1.1937 +    struct contact *contacts, *next, *prev, *curr;
  1.1938 +    int_str val;
  1.1939 +    int idx;
  1.1940 +    struct socket_info* sock;
  1.1941 +    unsigned int flags;
  1.1942 +
  1.1943 +    /* Check if anything needs to be done */
  1.1944 +    if (nr_branches == 0) {
  1.1945 +	LM_DBG("Nothing to do - no branches!\n");
  1.1946 +	return 1;
  1.1947 +    }
  1.1948 +
  1.1949 +    ruri = GET_RURI(msg);
  1.1950 +    if (!ruri) {
  1.1951 +	LM_ERR("No Request-URI found\n");
  1.1952 +	return -1;
  1.1953 +    }
  1.1954 +    ruri_q = get_ruri_q();
  1.1955 +
  1.1956 +    for(idx = 0; (uri.s = get_branch(idx, &uri.len, &q, 0, 0, 0, 0)) != 0;
  1.1957 +	idx++) {
  1.1958 +	if (q != ruri_q) {
  1.1959 +	    goto rest;
  1.1960 +	}
  1.1961 +    }
  1.1962 +    LM_DBG("Nothing to do - all contacts have same q!\n");
  1.1963 +    return 1;
  1.1964 +
  1.1965 +rest:
  1.1966 +    /* Insert Request-URI branch to contact list */
  1.1967 +    contacts = (struct contact *)pkg_malloc(sizeof(struct contact));
  1.1968 +    if (!contacts) {
  1.1969 +	LM_ERR("No memory for contact info\n");
  1.1970 +	return -1;
  1.1971 +    }
  1.1972 +    contacts->uri.s = ruri->s;
  1.1973 +    contacts->uri.len = ruri->len;
  1.1974 +    contacts->q = ruri_q;
  1.1975 +    contacts->dst_uri = msg->dst_uri;
  1.1976 +    contacts->sock = msg->force_send_socket;
  1.1977 +    contacts->flags = getb0flags();
  1.1978 +    contacts->path = msg->path_vec;
  1.1979 +    contacts->next = (struct contact *)0;
  1.1980 +
  1.1981 +    /* Insert branches to contact list in increasing q order */
  1.1982 +    for(idx = 0;
  1.1983 +	(uri.s = get_branch(idx,&uri.len,&q,&dst_uri,&path,&flags,&sock))
  1.1984 +	    != 0;
  1.1985 +	idx++ ) {
  1.1986 +	next = (struct contact *)pkg_malloc(sizeof(struct contact));
  1.1987 +	if (!next) {
  1.1988 +	    LM_ERR("No memory for contact info\n");
  1.1989 +	    free_contact_list(contacts);
  1.1990 +	    return -1;
  1.1991 +	}
  1.1992 +	next->uri = uri;
  1.1993 +	next->q = q;
  1.1994 +	next->dst_uri = dst_uri;
  1.1995 +	next->path = path;
  1.1996 +	next->flags = flags;
  1.1997 +	next->sock = sock;
  1.1998 +	next->next = (struct contact *)0;
  1.1999 +	prev = (struct contact *)0;
  1.2000 +	curr = contacts;
  1.2001 +	while (curr && (curr->q < q)) {
  1.2002 +	    prev = curr;
  1.2003 +	    curr = curr->next;
  1.2004 +	}
  1.2005 +	if (!curr) {
  1.2006 +	    next->next = (struct contact *)0;
  1.2007 +	    prev->next = next;
  1.2008 +	} else {
  1.2009 +	    next->next = curr;
  1.2010 +	    if (prev) {
  1.2011 +		prev->next = next;
  1.2012 +	    } else {
  1.2013 +		contacts = next;
  1.2014 +	    }
  1.2015 +	}		    
  1.2016 +    }
  1.2017 +
  1.2018 +    /* Assign values for q_flags */
  1.2019 +    curr = contacts;
  1.2020 +    curr->q_flag = 0;
  1.2021 +    while (curr->next) {
  1.2022 +	if (curr->q < curr->next->q) {
  1.2023 +	    curr->next->q_flag = Q_FLAG;
  1.2024 +	} else {
  1.2025 +	    curr->next->q_flag = 0;
  1.2026 +	}
  1.2027 +	curr = curr->next;
  1.2028 +    }
  1.2029 +
  1.2030 +    /* Add contacts to "contacts" AVP */
  1.2031 +    curr = contacts;
  1.2032 +    while (curr) {
  1.2033 +	if (encode_branch_info(&branch_info, curr) == 0) {
  1.2034 +	    LM_ERR("Encoding of branch info failed\n");
  1.2035 +	    free_contact_list(contacts);
  1.2036 +	    if (branch_info.s) pkg_free(branch_info.s);
  1.2037 +	    return -1;
  1.2038 +	}
  1.2039 +	val.s = branch_info;
  1.2040 +	add_avp(contact_avp_type|AVP_VAL_STR|(curr->q_flag),
  1.2041 +		contact_avp, val);
  1.2042 +	pkg_free(branch_info.s);
  1.2043 +	LM_DBG("Loaded contact <%.*s> with q_flag <%d>\n",
  1.2044 +	       val.s.len, val.s.s, curr->q_flag);
  1.2045 +	curr = curr->next;
  1.2046 +    }
  1.2047 +
  1.2048 +    /* Clear all branches */
  1.2049 +    clear_branches();
  1.2050 +
  1.2051 +    /* Free contact list */
  1.2052 +    free_contact_list(contacts);
  1.2053 +
  1.2054 +    return 1;
  1.2055 +}
  1.2056 +
  1.2057 +
  1.2058 +/*
  1.2059 + * Adds to request a destination set that includes all highest priority
  1.2060 + * class contacts in "lcr_contact" AVP.   If called from a route block,
  1.2061 + * rewrites the request uri with first contact and adds the remaining
  1.2062 + * contacts as branches.  If called from failure route block, adds all
  1.2063 + * contacts as branches.  Removes added contacts from "lcr_contact" AVP.
  1.2064 + */
  1.2065 +static int next_contacts(struct sip_msg* msg, char* key, char* value)
  1.2066 +{
  1.2067 +    struct usr_avp *avp, *prev;
  1.2068 +    int_str val;
  1.2069 +    str uri, dst, path;
  1.2070 +    struct socket_info *sock;
  1.2071 +    unsigned int flags;
  1.2072 +
  1.2073 +	/* Find first lcr_contact_avp value */
  1.2074 +	avp = search_first_avp(contact_avp_type, contact_avp, &val, 0);
  1.2075 +	if (!avp) {
  1.2076 +	    LM_DBG("No AVPs -- we are done!\n");
  1.2077 +	    return -1;
  1.2078 +	}
  1.2079 +
  1.2080 +	LM_DBG("Next contact is <%s>\n", val.s.s);
  1.2081 +
  1.2082 +	if (decode_branch_info(val.s.s, &uri, &dst, &path, &sock, &flags)== 0) {
  1.2083 +	    LM_ERR("Decoding of branch info <%.*s> failed\n",
  1.2084 +		   val.s.len, val.s.s);
  1.2085 +	    destroy_avp(avp);
  1.2086 +	    return -1;
  1.2087 +	}
  1.2088 +
  1.2089 +	set_ruri(msg, &uri);
  1.2090 +	set_dst_uri(msg, &dst);
  1.2091 +	set_path_vector(msg, &path);
  1.2092 +	msg->force_send_socket = sock;
  1.2093 +	setb0flags(flags);
  1.2094 +
  1.2095 +	if (avp->flags & Q_FLAG) {
  1.2096 +		destroy_avp(avp);
  1.2097 +		if (route_type == REQUEST_ROUTE) {
  1.2098 +			/* Set fr_inv_timer */
  1.2099 +			val.n = fr_inv_timer_next;
  1.2100 +			if (add_avp(fr_inv_timer_avp_type, fr_inv_timer_avp, val) != 0) {
  1.2101 +				LM_ERR("Setting of fr_inv_timer_avp failed\n");
  1.2102 +				return -1;
  1.2103 +			}
  1.2104 +		}
  1.2105 +		return 1;
  1.2106 +	}
  1.2107 +
  1.2108 +	/* Append branches until out of branches or Q_FLAG is set */
  1.2109 +	prev = avp;
  1.2110 +	while ((avp = search_next_avp(avp, &val))) {
  1.2111 +		destroy_avp(prev);
  1.2112 +
  1.2113 +		LM_DBG("Next contact is <%s>\n", val.s.s);
  1.2114 +
  1.2115 +		if (decode_branch_info(val.s.s, &uri, &dst, &path, &sock, &flags)== 0){
  1.2116 +			LM_ERR("Decoding of branch info <%.*s> failed\n",
  1.2117 +				val.s.len, val.s.s);
  1.2118 +			destroy_avp(avp);
  1.2119 +			return -1;
  1.2120 +		}
  1.2121 +
  1.2122 +		if (append_branch(msg, &uri, &dst, &path, 0, flags, sock) != 1) {
  1.2123 +			LM_ERR("Appending branch failed\n");
  1.2124 +			destroy_avp(avp);
  1.2125 +			return -1;
  1.2126 +		}
  1.2127 +
  1.2128 +		if (avp->flags & Q_FLAG) {
  1.2129 +			destroy_avp(avp);
  1.2130 +			if (route_type == REQUEST_ROUTE) {
  1.2131 +				val.n = fr_inv_timer_next;
  1.2132 +				if (add_avp(fr_inv_timer_avp_type, fr_inv_timer_avp, val)!= 0){
  1.2133 +					LM_ERR("Setting of fr_inv_timer_avp failed\n");
  1.2134 +					return -1;
  1.2135 +				}
  1.2136 +			}
  1.2137 +			return 1;
  1.2138 +		}
  1.2139 +		prev = avp;
  1.2140 +	}
  1.2141 +
  1.2142 +	/* Restore fr_inv_timer */
  1.2143 +	val.n = fr_inv_timer;
  1.2144 +	if (add_avp(fr_inv_timer_avp_type, fr_inv_timer_avp, val) != 0) {
  1.2145 +		LM_ERR("Setting of fr_inv_timer_avp failed\n");
  1.2146 +		return -1;
  1.2147 +	}
  1.2148 +
  1.2149 +	return 1;
  1.2150 +}
  1.2151 +
  1.2152 +
  1.2153 +/* 
  1.2154 + * Convert string parameter to integer for functions that expect an integer.
  1.2155 + * Taken from sl module.
  1.2156 + */
  1.2157 +static int fixstringloadgws(void **param, int param_count)
  1.2158 +{
  1.2159 +    pv_elem_t *model=NULL;
  1.2160 +    str s;
  1.2161 +
  1.2162 +    /* convert to str */
  1.2163 +    s.s = (char*)*param;
  1.2164 +    s.len = strlen(s.s);
  1.2165 +
  1.2166 +    model=NULL;
  1.2167 +    if (param_count==1) {
  1.2168 +	if(s.len==0) {
  1.2169 +	    LM_ERR("No param <%d>!\n", param_count);
  1.2170 +	    return -1;
  1.2171 +	}
  1.2172 +	
  1.2173 +	if(pv_parse_format(&s,&model)<0 || model==NULL) {
  1.2174 +	    LM_ERR("Wrong format <%s> for param <%d>!\n", s.s, param_count);
  1.2175 +	    return -1;
  1.2176 +	}
  1.2177 +	if(model->spec.getf==NULL) {
  1.2178 +	    if(param_count==1) {
  1.2179 +		if(str2int(&s, (unsigned int*)&model->spec.pvp.pvn.u.isname.name.n)!=0) {
  1.2180 +		    LM_ERR("Wrong value <%s> for param <%d>!\n",
  1.2181 +			   s.s, param_count);
  1.2182 +		    return -1;
  1.2183 +		}
  1.2184 +	    }
  1.2185 +	}
  1.2186 +	*param = (void*)model;
  1.2187 +    }
  1.2188 +
  1.2189 +    return 0;
  1.2190 +}
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/opensips/modules/uac/auth.c	Wed Feb 10 21:14:04 2010 +0100
     2.3 @@ -0,0 +1,468 @@
     2.4 +/*
     2.5 + * $Id: auth.c 5901 2009-07-21 07:45:05Z bogdan_iancu $
     2.6 + *
     2.7 + * Copyright (C) 2005 Voice Sistem SRL
     2.8 + *
     2.9 + * This file is part of opensips, a free SIP server.
    2.10 + *
    2.11 + * UAC OpenSIPS-module is free software; you can redistribute it and/or
    2.12 + * modify it under the terms of the GNU General Public License
    2.13 + * as published by the Free Software Foundation; either version 2
    2.14 + * of the License, or (at your option) any later version.
    2.15 + *
    2.16 + * UAC OpenSIPS-module is distributed in the hope that it will be useful,
    2.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2.19 + * GNU General Public License for more details.
    2.20 + *
    2.21 + * You should have received a copy of the GNU General Public License
    2.22 + * along with this program; if not, write to the Free Software
    2.23 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    2.24 + *
    2.25 + *
    2.26 + * History:
    2.27 + * ---------
    2.28 + *  2005-01-31  first version (ramona)
    2.29 + *  2006-03-02  UAC authentication looks first in AVPs for credential (bogdan)
    2.30 + */
    2.31 +
    2.32 +
    2.33 +#include <ctype.h>
    2.34 +#include <string.h>
    2.35 +
    2.36 +#include "../../str.h"
    2.37 +#include "../../dprint.h"
    2.38 +#include "../../pvar.h"
    2.39 +#include "../../data_lump.h"
    2.40 +#include "../../mem/mem.h"
    2.41 +#include "../tm/tm_load.h"
    2.42 +
    2.43 +#include "auth.h"
    2.44 +#include "auth_alg.h"
    2.45 +#include "auth_hdr.h"
    2.46 +
    2.47 +
    2.48 +extern struct tm_binds uac_tmb;
    2.49 +extern pv_spec_t auth_username_spec;
    2.50 +extern pv_spec_t auth_realm_spec;
    2.51 +extern pv_spec_t auth_password_spec;
    2.52 +
    2.53 +
    2.54 +static struct uac_credential *crd_list = 0;
    2.55 +
    2.56 +
    2.57 +#define  duplicate_str(_strd, _strs, _error) \
    2.58 +	do { \
    2.59 +		_strd.s = (char*)pkg_malloc(_strs.len); \
    2.60 +		if (_strd.s==0) \
    2.61 +		{ \
    2.62 +			LM_ERR("no more pkg memory\n");\
    2.63 +			goto _error; \
    2.64 +		} \
    2.65 +		memcpy( _strd.s, _strs.s, _strs.len); \
    2.66 +		_strd.len = _strs.len; \
    2.67 +	}while(0)
    2.68 +
    2.69 +
    2.70 +#define WWW_AUTH_CODE       401
    2.71 +#define WWW_AUTH_HDR        "WWW-Authenticate"
    2.72 +#define WWW_AUTH_HDR_LEN    (sizeof(WWW_AUTH_HDR)-1)
    2.73 +#define PROXY_AUTH_CODE     407
    2.74 +#define PROXY_AUTH_HDR      "Proxy-Authenticate"
    2.75 +#define PROXY_AUTH_HDR_LEN  (sizeof(PROXY_AUTH_HDR)-1)
    2.76 +
    2.77 +static str nc = {"00000001", 8};
    2.78 +static str cnonce = {"o", 1};
    2.79 +
    2.80 +int has_credentials(void)
    2.81 +{
    2.82 +	return (crd_list!=0)?1:0;
    2.83 +}
    2.84 +
    2.85 +void free_credential(struct uac_credential *crd)
    2.86 +{
    2.87 +	if (crd)
    2.88 +	{
    2.89 +		if (crd->realm.s)
    2.90 +			pkg_free(crd->realm.s);
    2.91 +		if (crd->user.s)
    2.92 +			pkg_free(crd->user.s);
    2.93 +		if (crd->passwd.s)
    2.94 +			pkg_free(crd->passwd.s);
    2.95 +		pkg_free(crd);
    2.96 +	}
    2.97 +}
    2.98 +
    2.99 +
   2.100 +int add_credential( unsigned int type, void *val)
   2.101 +{
   2.102 +	struct uac_credential *crd;
   2.103 +	char *p;
   2.104 +	str foo;
   2.105 +
   2.106 +	p = (char*)val;
   2.107 +	crd = 0;
   2.108 +
   2.109 +	if (p==0 || *p==0)
   2.110 +		goto error;
   2.111 +
   2.112 +	crd = (struct uac_credential*)pkg_malloc(sizeof(struct uac_credential));
   2.113 +	if (crd==0)
   2.114 +	{
   2.115 +		LM_ERR("no more pkg mem\n");
   2.116 +		goto error;
   2.117 +	}
   2.118 +	memset( crd, 0, sizeof(struct uac_credential));
   2.119 +
   2.120 +	/*parse the user */
   2.121 +	while (*p && isspace((int)*p)) p++;
   2.122 +	foo.s = p;
   2.123 +	while (*p && *p!=':' && !isspace((int)*p)) p++;
   2.124 +	if (foo.s==p || *p==0)
   2.125 +		/* missing or empty user */
   2.126 +		goto parse_error;
   2.127 +	foo.len = p - foo.s;
   2.128 +	/* dulicate it */
   2.129 +	duplicate_str( crd->user, foo, error);
   2.130 +
   2.131 +	/* parse the ':' separator */
   2.132 +	while (*p && isspace((int)*p)) p++;
   2.133 +	if (*p!=':')
   2.134 +		goto parse_error;
   2.135 +	p++;
   2.136 +	while (*p && isspace((int)*p)) p++;
   2.137 +	if (*p==0)
   2.138 +		goto parse_error;
   2.139 +
   2.140 +	/*parse the realm */
   2.141 +	while (*p && isspace((int)*p)) p++;
   2.142 +	foo.s = p;
   2.143 +	while (*p && *p!=':' && !isspace((int)*p)) p++;
   2.144 +	if (foo.s==p || *p==0)
   2.145 +		/* missing or empty realm */
   2.146 +		goto parse_error;
   2.147 +	foo.len = p - foo.s;
   2.148 +	/* dulicate it */
   2.149 +	duplicate_str( crd->realm, foo, error);
   2.150 +
   2.151 +	/* parse the ':' separator */
   2.152 +	while (*p && isspace((int)*p)) p++;
   2.153 +	if (*p!=':')
   2.154 +		goto parse_error;
   2.155 +	p++;
   2.156 +	while (*p && isspace((int)*p)) p++;
   2.157 +	if (*p==0)
   2.158 +		goto parse_error;
   2.159 +
   2.160 +	/*parse the passwd */
   2.161 +	while (*p && isspace((int)*p)) p++;
   2.162 +	foo.s = p;
   2.163 +	while (*p && !isspace((int)*p)) p++;
   2.164 +	if (foo.s==p)
   2.165 +		/* missing or empty passwd */
   2.166 +		goto parse_error;
   2.167 +	foo.len = p - foo.s;
   2.168 +	/* dulicate it */
   2.169 +	duplicate_str( crd->passwd, foo, error);
   2.170 +
   2.171 +	/* end of string */
   2.172 +	while (*p && isspace((int)*p)) p++;
   2.173 +	if (*p!=0)
   2.174 +		goto parse_error;
   2.175 +
   2.176 +	/* link the new cred struct */
   2.177 +	crd->next = crd_list;
   2.178 +	crd_list = crd;
   2.179 +
   2.180 +	pkg_free(val);
   2.181 +	return 0;
   2.182 +parse_error:
   2.183 +		LM_ERR("parse error in <%s> "
   2.184 +		"around %ld\n", (char*)val, (long)(p-(char*)val));
   2.185 +error:
   2.186 +	if (crd)
   2.187 +		free_credential(crd);
   2.188 +	return -1;
   2.189 +}
   2.190 +
   2.191 +
   2.192 +void destroy_credentials(void)
   2.193 +{
   2.194 +	struct uac_credential *foo;
   2.195 +
   2.196 +	while (crd_list)
   2.197 +	{
   2.198 +		foo = crd_list;
   2.199 +		crd_list = crd_list->next;
   2.200 +		free_credential(foo);
   2.201 +	}
   2.202 +	crd_list = 0;
   2.203 +}
   2.204 +
   2.205 +
   2.206 +static inline struct hdr_field *get_autenticate_hdr(struct sip_msg *rpl,
   2.207 +																int rpl_code)
   2.208 +{
   2.209 +	struct hdr_field *hdr;
   2.210 +	str hdr_name;
   2.211 +
   2.212 +	/* what hdr should we look for */
   2.213 +	if (rpl_code==WWW_AUTH_CODE)
   2.214 +	{
   2.215 +		hdr_name.s = WWW_AUTH_HDR;
   2.216 +		hdr_name.len = WWW_AUTH_HDR_LEN;
   2.217 +	} else if (rpl_code==PROXY_AUTH_CODE) {
   2.218 +		hdr_name.s = PROXY_AUTH_HDR;
   2.219 +		hdr_name.len = PROXY_AUTH_HDR_LEN;
   2.220 +	} else {
   2.221 +		LM_ERR("reply is not an "
   2.222 +			"auth request\n");
   2.223 +		goto error;
   2.224 +	}
   2.225 +
   2.226 +	LM_DBG("looking for header \"%.*s\"\n",
   2.227 +		hdr_name.len, hdr_name.s);
   2.228 +
   2.229 +	/* search the auth hdr, but first parse them all */
   2.230 +	if (parse_headers( rpl, HDR_EOH_F, 0)<0)
   2.231 +	{
   2.232 +		LM_ERR("failed to parse reply\n");
   2.233 +		goto error;
   2.234 +	}
   2.235 +	hdr = get_header_by_name( rpl , hdr_name.s, hdr_name.len);
   2.236 +	if (hdr)
   2.237 +		return hdr;
   2.238 +
   2.239 +	LM_ERR("reply has no "
   2.240 +		"auth hdr (%.*s)\n", hdr_name.len, hdr_name.s);
   2.241 +error:
   2.242 +	return 0;
   2.243 +}
   2.244 +
   2.245 +
   2.246 +static inline struct uac_credential *lookup_realm( str *realm)
   2.247 +{
   2.248 +	struct uac_credential *crd;
   2.249 +
   2.250 +	for( crd=crd_list ; crd ; crd=crd->next )
   2.251 +		if (realm->len==crd->realm.len &&
   2.252 +		strncmp( realm->s, crd->realm.s, realm->len)==0 )
   2.253 +			return crd;
   2.254 +	return 0;
   2.255 +}
   2.256 +
   2.257 +
   2.258 +static inline struct uac_credential *get_avp_credential(struct sip_msg *msg,
   2.259 +																str *realm)
   2.260 +{
   2.261 +	static struct uac_credential crd;
   2.262 +	pv_value_t pv_val;
   2.263 +
   2.264 +	if(pv_get_spec_value( msg, &auth_realm_spec, &pv_val)!=0
   2.265 +	|| pv_val.flags&PV_VAL_NULL || pv_val.rs.len<=0)
   2.266 +		return 0;
   2.267 +	
   2.268 +	crd.realm = pv_val.rs;
   2.269 +	/* is it the domain we are looking for? */
   2.270 +	if (realm->len!=crd.realm.len ||
   2.271 +	strncmp( realm->s, crd.realm.s, realm->len)!=0 )
   2.272 +		return 0;
   2.273 +
   2.274 +	/* get username and password */
   2.275 +	if(pv_get_spec_value( msg, &auth_username_spec, &pv_val)!=0
   2.276 +	|| pv_val.flags&PV_VAL_NULL || pv_val.rs.len<=0)
   2.277 +		return 0;
   2.278 +	crd.user = pv_val.rs;
   2.279 +
   2.280 +	if(pv_get_spec_value( msg, &auth_password_spec, &pv_val)!=0
   2.281 +	|| pv_val.flags&PV_VAL_NULL || pv_val.rs.len<=0)
   2.282 +		return 0;
   2.283 +	crd.passwd = pv_val.rs;
   2.284 +
   2.285 +	return &crd;
   2.286 +}
   2.287 +
   2.288 +
   2.289 +static inline void do_uac_auth(struct sip_msg *req, str *uri,
   2.290 +		struct uac_credential *crd, struct authenticate_body *auth,
   2.291 +		HASHHEX response)
   2.292 +{
   2.293 +	HASHHEX ha1;
   2.294 +	HASHHEX ha2;
   2.295 +
   2.296 +	if((auth->flags&QOP_AUTH) || (auth->flags&QOP_AUTH_INT))
   2.297 +	{
   2.298 +		/* if qop generate nonce-count and cnonce */
   2.299 +		cnonce.s = int2str(core_hash(&auth->nonce, 0, 0),&cnonce.len);
   2.300 +
   2.301 +		/* do authentication */
   2.302 +		uac_calc_HA1( crd, auth, &cnonce, ha1);
   2.303 +		uac_calc_HA2( &req->first_line.u.request.method, uri,
   2.304 +			auth, 0/*hentity*/, ha2 );
   2.305 +
   2.306 +		uac_calc_response( ha1, ha2, auth, &nc, &cnonce, response);
   2.307 +		auth->nc = &nc;
   2.308 +		auth->cnonce = &cnonce;
   2.309 +	} else {
   2.310 +		/* do authentication */
   2.311 +		uac_calc_HA1( crd, auth, 0/*cnonce*/, ha1);
   2.312 +		uac_calc_HA2( &req->first_line.u.request.method, uri,
   2.313 +			auth, 0/*hentity*/, ha2 );
   2.314 +
   2.315 +		uac_calc_response( ha1, ha2, auth, 0/*nc*/, 0/*cnonce*/, response);
   2.316 +	}
   2.317 +}
   2.318 +
   2.319 +
   2.320 +static inline int apply_urihdr_changes( struct sip_msg *req,
   2.321 +													str *uri, str *hdr)
   2.322 +{
   2.323 +	struct lump* anchor;
   2.324 +
   2.325 +	/* add the uri - move it to branch directly FIXME (bogdan)*/
   2.326 +	if (req->new_uri.s)
   2.327 +	{
   2.328 +		pkg_free(req->new_uri.s);
   2.329 +		req->new_uri.len=0;
   2.330 +	}
   2.331 +	req->parsed_uri_ok=0;
   2.332 +	req->new_uri.s = (char*)pkg_malloc(uri->len+1);
   2.333 +	if (req->new_uri.s==0)
   2.334 +	{
   2.335 +		LM_ERR("no more pkg\n");
   2.336 +		goto error;
   2.337 +	}
   2.338 +	memcpy( req->new_uri.s, uri->s, uri->len);
   2.339 +	req->new_uri.s[uri->len]=0;
   2.340 +	req->new_uri.len=uri->len;
   2.341 +
   2.342 +	/* add the header */
   2.343 +	if (parse_headers(req, HDR_EOH_F, 0) == -1)
   2.344 +	{
   2.345 +		LM_ERR("failed to parse message\n");
   2.346 +		goto error;
   2.347 +	}
   2.348 +
   2.349 +	anchor = anchor_lump(req, req->unparsed - req->buf, 0, 0);
   2.350 +	if (anchor==0)
   2.351 +	{
   2.352 +		LM_ERR("failed to get anchor\n");
   2.353 +		goto error;
   2.354 +	}
   2.355 +
   2.356 +	if (insert_new_lump_before(anchor, hdr->s, hdr->len, 0) == 0)
   2.357 +	{
   2.358 +		LM_ERR("faield to insert lump\n");
   2.359 +		goto error;
   2.360 +	}
   2.361 +
   2.362 +	return 0;
   2.363 +error:
   2.364 +	pkg_free( hdr->s );
   2.365 +	return -1;
   2.366 +}
   2.367 +
   2.368 +
   2.369 +
   2.370 +int uac_auth( struct sip_msg *msg)
   2.371 +{
   2.372 +	static struct authenticate_body auth;
   2.373 +	struct uac_credential *crd;
   2.374 +	int code, branch;
   2.375 +	struct sip_msg *rpl;
   2.376 +	struct cell *t;
   2.377 +	struct hdr_field *hdr;
   2.378 +	HASHHEX response;
   2.379 +	str *new_hdr;
   2.380 +
   2.381 +	/* get transaction */
   2.382 +	t = uac_tmb.t_gett();
   2.383 +	if (t==T_UNDEFINED || t==T_NULL_CELL)
   2.384 +	{
   2.385 +		LM_CRIT("no current transaction found\n");
   2.386 +		goto error;
   2.387 +	}
   2.388 +
   2.389 +	/* get the selected branch */
   2.390 +	branch = uac_tmb.t_get_picked();
   2.391 +	if (branch<0) {
   2.392 +		LM_CRIT("no picked branch (%d)\n",branch);
   2.393 +		goto error;
   2.394 +	}
   2.395 +
   2.396 +	rpl = t->uac[branch].reply;
   2.397 +	code = t->uac[branch].last_received;
   2.398 +	LM_DBG("picked reply is %p, code %d\n",rpl,code);
   2.399 +
   2.400 +	if (rpl==0)
   2.401 +	{
   2.402 +		LM_CRIT("empty reply on picked branch\n");
   2.403 +		goto error;
   2.404 +	}
   2.405 +	if (rpl==FAKED_REPLY)
   2.406 +	{
   2.407 +		LM_ERR("cannot process a FAKED reply\n");
   2.408 +		goto error;
   2.409 +	}
   2.410 +
   2.411 +	hdr = get_autenticate_hdr( rpl, code);
   2.412 +	if (hdr==0)
   2.413 +	{
   2.414 +		LM_ERR("failed to extract authenticate hdr\n");
   2.415 +		goto error;
   2.416 +	}
   2.417 +
   2.418 +	LM_DBG("header found; body=<%.*s>\n",
   2.419 +		hdr->body.len, hdr->body.s);
   2.420 +
   2.421 +	if (parse_authenticate_body( &hdr->body, &auth)<0)
   2.422 +	{
   2.423 +		LM_ERR("failed to parse auth hdr body\n");
   2.424 +		goto error;
   2.425 +	}
   2.426 +
   2.427 +	/* can we authenticate this realm? */
   2.428 +	crd = 0;
   2.429 +	/* first look into AVP, if set */
   2.430 +	if ( auth_realm_spec.type==PVT_AVP )
   2.431 +		crd = get_avp_credential( msg, &auth.realm );
   2.432 +	/* if not found, look into predefined credentials */
   2.433 +	if (crd==0)
   2.434 +		crd = lookup_realm( &auth.realm );
   2.435 +	/* found? */
   2.436 +	if (crd==0)
   2.437 +	{
   2.438 +		LM_DBG("no credential for realm \"%.*s\"\n",
   2.439 +			auth.realm.len, auth.realm.s);
   2.440 +		goto error;
   2.441 +	}
   2.442 +
   2.443 +	/* do authentication */
   2.444 +	do_uac_auth( msg, &t->uac[branch].uri, crd, &auth, response);
   2.445 +
   2.446 +	/* build the authorization header */
   2.447 +	new_hdr = build_authorization_hdr( code, &t->uac[branch].uri,
   2.448 +		crd, &auth, response);
   2.449 +	if (new_hdr==0)
   2.450 +	{
   2.451 +		LM_ERR("failed to build authorization hdr\n");
   2.452 +		goto error;
   2.453 +	}
   2.454 +
   2.455 +	/* so far, so good -> add the header and set the proper RURI */
   2.456 +	if ( apply_urihdr_changes( msg, &t->uac[branch].uri, new_hdr)<0 )
   2.457 +	{
   2.458 +		LM_ERR("failed to apply changes\n");
   2.459 +		goto error;
   2.460 +	}
   2.461 +
   2.462 +	/* increas the Cseq nr */
   2.463 +
   2.464 +
   2.465 +	return 0;
   2.466 +error:
   2.467 +	return -1;
   2.468 +}
   2.469 +
   2.470 +
   2.471 +
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/opensips/modules/uac/uac.c	Wed Feb 10 21:14:04 2010 +0100
     3.3 @@ -0,0 +1,420 @@
     3.4 +/*
     3.5 + * $Id: uac.c 6481 2009-12-29 13:49:37Z bogdan_iancu $
     3.6 + *
     3.7 + * Copyright (C) 2005-2009 Voice Sistem SRL
     3.8 + *
     3.9 + * This file is part of opensips, a free SIP server.
    3.10 + *
    3.11 + * UAC OpenSIPS-module is free software; you can redistribute it and/or
    3.12 + * modify it under the terms of the GNU General Public License
    3.13 + * as published by the Free Software Foundation; either version 2
    3.14 + * of the License, or (at your option) any later version.
    3.15 + *
    3.16 + * UAC OpenSIPS-module is distributed in the hope that it will be useful,
    3.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    3.19 + * GNU General Public License for more details.
    3.20 + *
    3.21 + * You should have received a copy of the GNU General Public License
    3.22 + * along with this program; if not, write to the Free Software
    3.23 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    3.24 + *
    3.25 + *
    3.26 + * History:
    3.27 + * ---------
    3.28 + *  2005-01-31  first version (ramona)
    3.29 + *  2005-08-12  some TM callbacks replaced with RR callback - more efficient;
    3.30 + *              (bogdan)
    3.31 + *  2006-03-02  UAC authentication looks first in AVPs for credential (bogdan)
    3.32 + *  2006-03-03  the RR parameter is encrypted via XOR with a password
    3.33 + *              (bogdan)
    3.34 + *  2009-08-22  TO header replacement added (bogdan)
    3.35 +
    3.36 + */
    3.37 +
    3.38 +
    3.39 +#include <stdio.h>
    3.40 +#include <string.h>
    3.41 +#include <stdlib.h>
    3.42 +
    3.43 +#include "../../sr_module.h"
    3.44 +#include "../../dprint.h"
    3.45 +#include "../../error.h"
    3.46 +#include "../../pvar.h"
    3.47 +#include "../../mem/mem.h"
    3.48 +#include "../../parser/parse_from.h"
    3.49 +#include "../tm/tm_load.h"
    3.50 +#include "../tm/t_hooks.h"
    3.51 +#include "../rr/api.h"
    3.52 +
    3.53 +#include "replace.h"
    3.54 +#include "auth.h"
    3.55 +
    3.56 +
    3.57 +
    3.58 +
    3.59 +
    3.60 +/* local variable used for init */
    3.61 +static char* restore_mode_str = NULL;
    3.62 +static char* auth_username_avp = NULL;
    3.63 +static char* auth_realm_avp = NULL;
    3.64 +static char* auth_password_avp = NULL;
    3.65 +
    3.66 +/* global param variables */
    3.67 +str rr_from_param = str_init("vsf");
    3.68 +str rr_to_param = str_init("vst");
    3.69 +str uac_passwd = str_init("");
    3.70 +int restore_mode = UAC_AUTO_RESTORE;
    3.71 +struct tm_binds uac_tmb;
    3.72 +struct rr_binds uac_rrb;
    3.73 +pv_spec_t auth_username_spec;
    3.74 +pv_spec_t auth_realm_spec;
    3.75 +pv_spec_t auth_password_spec;
    3.76 +
    3.77 +static int w_replace_from(struct sip_msg* msg, char* p1, char* p2);
    3.78 +static int w_restore_from(struct sip_msg* msg);
    3.79 +
    3.80 +static int w_replace_to(struct sip_msg* msg, char* p1, char* p2);
    3.81 +static int w_restore_to(struct sip_msg* msg);
    3.82 +
    3.83 +static int w_uac_auth(struct sip_msg* msg, char* str, char* str2);
    3.84 +static int fixup_replace_uri(void** param, int param_no);
    3.85 +static int fixup_replace_disp_uri(void** param, int param_no);
    3.86 +static int mod_init(void);
    3.87 +static void mod_destroy(void);
    3.88 +
    3.89 +
    3.90 +/* Exported functions */
    3.91 +static cmd_export_t cmds[]={
    3.92 +	{"uac_replace_from",  (cmd_function)w_replace_from,  2,
    3.93 +			fixup_replace_disp_uri, 0,
    3.94 +			REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE },
    3.95 +	{"uac_replace_from",  (cmd_function)w_replace_from,  1,
    3.96 +			fixup_replace_uri, 0,
    3.97 +			REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE },
    3.98 +	{"uac_restore_from",  (cmd_function)w_restore_from,   0,
    3.99 +			0, 0,
   3.100 +			REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE },
   3.101 +	{"uac_replace_to",  (cmd_function)w_replace_to,  2,
   3.102 +			fixup_replace_disp_uri, 0,
   3.103 +			REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE },
   3.104 +	{"uac_replace_to",  (cmd_function)w_replace_to,  1,
   3.105 +			fixup_replace_uri, 0,
   3.106 +			REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE },
   3.107 +	{"uac_restore_to",  (cmd_function)w_restore_to,   0,
   3.108 +			0, 0,
   3.109 +			REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE },
   3.110 +	{"uac_auth",          (cmd_function)w_uac_auth,       0,
   3.111 +			0, 0,
   3.112 +			FAILURE_ROUTE },
   3.113 +	{0,0,0,0,0,0}
   3.114 +};
   3.115 +
   3.116 +
   3.117 +
   3.118 +/* Exported parameters */
   3.119 +static param_export_t params[] = {
   3.120 +	{"rr_from_store_param", STR_PARAM,                &rr_from_param.s       },
   3.121 +	{"rr_to_store_param",   STR_PARAM,                &rr_to_param.s         },
   3.122 +	{"restore_mode",        STR_PARAM,                &restore_mode_str      },
   3.123 +	{"restore_passwd",      STR_PARAM,                &uac_passwd.s          },
   3.124 +	{"credential",          STR_PARAM|USE_FUNC_PARAM, (void*)&add_credential },
   3.125 +	{"auth_username_avp",   STR_PARAM,                &auth_username_avp     },
   3.126 +	{"auth_realm_avp",      STR_PARAM,                &auth_realm_avp        },
   3.127 +	{"auth_password_avp",   STR_PARAM,                &auth_password_avp     },
   3.128 +	{0, 0, 0}
   3.129 +};
   3.130 +
   3.131 +
   3.132 +
   3.133 +struct module_exports exports= {
   3.134 +	"uac",
   3.135 +	MODULE_VERSION,
   3.136 +	DEFAULT_DLFLAGS, /* dlopen flags */
   3.137 +	cmds,       /* exported functions */
   3.138 +	params,     /* param exports */
   3.139 +	0,          /* exported statistics */
   3.140 +	0,          /* exported MI functions */
   3.141 +	0,          /* exported pseudo-variables */
   3.142 +	0,          /* extra processes */
   3.143 +	mod_init,   /* module initialization function */
   3.144 +	(response_function) 0,
   3.145 +	mod_destroy,
   3.146 +	0  /* per-child init function */
   3.147 +};
   3.148 +
   3.149 +
   3.150 +inline static int parse_auth_avp( char *avp_spec, pv_spec_t *avp, char *txt)
   3.151 +{
   3.152 +	str s;
   3.153 +	s.s = avp_spec; s.len = strlen(s.s);
   3.154 +	if (pv_parse_spec(&s, avp)==NULL) {
   3.155 +		LM_ERR("malformed or non AVP %s AVP definition\n",txt);
   3.156 +		return -1;
   3.157 +	}
   3.158 +	return 0;
   3.159 +}
   3.160 +
   3.161 +
   3.162 +static int mod_init(void)
   3.163 +{
   3.164 +	LM_INFO("initializing...\n");
   3.165 +
   3.166 +	if (restore_mode_str && *restore_mode_str) {
   3.167 +		if (strcasecmp(restore_mode_str,"none")==0) {
   3.168 +			restore_mode = UAC_NO_RESTORE;
   3.169 +		} else if (strcasecmp(restore_mode_str,"manual")==0) {
   3.170 +			restore_mode = UAC_MANUAL_RESTORE;
   3.171 +		} else if (strcasecmp(restore_mode_str,"auto")==0) {
   3.172 +			restore_mode = UAC_AUTO_RESTORE;
   3.173 +		} else {
   3.174 +			LM_ERR("unsupported value '%s' for restore_mode\n",
   3.175 +				restore_mode_str);
   3.176 +			goto error;
   3.177 +		}
   3.178 +	}
   3.179 +
   3.180 +	rr_from_param.len = strlen(rr_from_param.s);
   3.181 +	rr_to_param.len = strlen(rr_to_param.s);
   3.182 +	if ( (rr_from_param.len==0 || rr_to_param.len==0) &&
   3.183 +	restore_mode!=UAC_NO_RESTORE)
   3.184 +	{
   3.185 +		LM_ERR("rr_store_param cannot be empty if FROM is restoreable\n");
   3.186 +		goto error;
   3.187 +	}
   3.188 +
   3.189 +	uac_passwd.len = strlen(uac_passwd.s);
   3.190 +
   3.191 +	/* parse the auth AVP spesc, if any */
   3.192 +	if ( auth_username_avp || auth_password_avp || auth_realm_avp) {
   3.193 +		if (!auth_username_avp || !auth_password_avp || !auth_realm_avp) {
   3.194 +			LM_ERR("partial definition of auth AVP!");
   3.195 +			goto error;
   3.196 +		}
   3.197 +		if ( parse_auth_avp(auth_realm_avp, &auth_realm_spec, "realm")<0
   3.198 +		|| parse_auth_avp(auth_username_avp, &auth_username_spec, "username")<0
   3.199 +		|| parse_auth_avp(auth_password_avp, &auth_password_spec, "password")<0
   3.200 +		) {
   3.201 +			goto error;
   3.202 +		}
   3.203 +	} else {
   3.204 +		memset( &auth_realm_spec, 0, sizeof(pv_spec_t));
   3.205 +		memset( &auth_password_spec, 0, sizeof(pv_spec_t));
   3.206 +		memset( &auth_username_spec, 0, sizeof(pv_spec_t));
   3.207 +	}
   3.208 +
   3.209 +	/* load the TM API - FIXME it should be loaded only
   3.210 +	 * if NO_RESTORE and AUTH */
   3.211 +	if (load_tm_api(&uac_tmb)!=0) {
   3.212 +		LM_ERR("can't load TM API\n");
   3.213 +		goto error;
   3.214 +	}
   3.215 +
   3.216 +	if (restore_mode!=UAC_NO_RESTORE) {
   3.217 +		/* load the RR API */
   3.218 +		if (load_rr_api(&uac_rrb)!=0) {
   3.219 +			LM_ERR("can't load RR API\n");
   3.220 +			goto error;
   3.221 +		}
   3.222 +
   3.223 +		if (restore_mode==UAC_AUTO_RESTORE) {
   3.224 +			/* we need the append_fromtag on in RR */
   3.225 +			if (!uac_rrb.append_fromtag) {
   3.226 +				LM_ERR("'append_fromtag' RR param is not enabled!"
   3.227 +					" - required by AUTO restore mode\n");
   3.228 +				goto error;
   3.229 +			}
   3.230 +			/* get all requests doing loose route */
   3.231 +			if (uac_rrb.register_rrcb( rr_checker, 0)!=0) {
   3.232 +				LM_ERR("failed to install RR callback\n");
   3.233 +				goto error;
   3.234 +			}
   3.235 +		}
   3.236 +	}
   3.237 +
   3.238 +	init_from_replacer();
   3.239 +
   3.240 +	return 0;
   3.241 +error:
   3.242 +	return -1;
   3.243 +}
   3.244 +
   3.245 +
   3.246 +static void mod_destroy(void)
   3.247 +{
   3.248 +	destroy_credentials();
   3.249 +}
   3.250 +
   3.251 +
   3.252 +
   3.253 +/************************** fixup functions ******************************/
   3.254 +
   3.255 +static int fixup_replace_uri(void** param, int param_no)
   3.256 +{
   3.257 +	pv_elem_t *model;
   3.258 +	str s;
   3.259 +
   3.260 +	model=NULL;
   3.261 +	s.s = (char*)(*param); s.len = strlen(s.s);
   3.262 +	if(pv_parse_format(&s, &model)<0)
   3.263 +	{
   3.264 +		LM_ERR("wrong format[%s]!\n",(char*)(*param));
   3.265 +		return E_UNSPEC;
   3.266 +	}
   3.267 +	if (model==NULL)
   3.268 +	{
   3.269 +		LM_ERR("empty parameter!\n");
   3.270 +		return E_UNSPEC;
   3.271 +	}
   3.272 +	*param = (void*)model;
   3.273 +
   3.274 +	return 0;
   3.275 +}
   3.276 +
   3.277 +
   3.278 +static int fixup_replace_disp_uri(void** param, int param_no)
   3.279 +{
   3.280 +	pv_elem_t *model;
   3.281 +	char *p;
   3.282 +	str s;
   3.283 +
   3.284 +	/* convert to str */
   3.285 +	s.s = (char*)*param;
   3.286 +	s.len = strlen(s.s);
   3.287 +
   3.288 +	model=NULL;
   3.289 +	if (param_no==1 && s.len) {
   3.290 +		/* put " around display name */
   3.291 +		p = (char*)pkg_malloc(s.len+3);
   3.292 +		if (p==0) {
   3.293 +			LM_CRIT("no more pkg mem\n");
   3.294 +			return E_OUT_OF_MEM;
   3.295 +		}
   3.296 +		p[0] = '\"';
   3.297 +		memcpy(p+1, s.s, s.len);
   3.298 +		p[s.len+1] = '\"';
   3.299 +		p[s.len+2] = '\0';
   3.300 +		pkg_free(s.s);
   3.301 +		s.s = p;
   3.302 +		s.len += 2;
   3.303 +	}
   3.304 +	if(pv_parse_format(&s ,&model)<0) {
   3.305 +		LM_ERR("wrong format [%s] for param no %d!\n", s.s, param_no);
   3.306 +		pkg_free(s.s);
   3.307 +		return E_UNSPEC;
   3.308 +	}
   3.309 +	*param = (void*)model;
   3.310 +
   3.311 +	return 0;
   3.312 +}
   3.313 +
   3.314 +
   3.315 +
   3.316 +/************************** wrapper functions ******************************/
   3.317 +
   3.318 +static int w_restore_from(struct sip_msg *msg)
   3.319 +{
   3.320 +	/* safety checks - must be a request */
   3.321 +	if (msg->first_line.type!=SIP_REQUEST) {
   3.322 +		LM_ERR("called for something not request\n");
   3.323 +		return -1;
   3.324 +	}
   3.325 +
   3.326 +	return (restore_uri(msg,&rr_from_param,1)==0)?1:-1;
   3.327 +}
   3.328 +
   3.329 +
   3.330 +static int w_replace_from(struct sip_msg* msg, char* p1, char* p2)
   3.331 +{
   3.332 +	str uri_s;
   3.333 +	str dsp_s;
   3.334 +	str *uri;
   3.335 +	str *dsp;
   3.336 +
   3.337 +	if (p2==NULL) {
   3.338 +		p2 = p1;
   3.339 +		p1 = NULL;
   3.340 +		dsp = NULL;
   3.341 +	}
   3.342 +
   3.343 +	/* p1 dispaly , p2 uri */
   3.344 +
   3.345 +	if ( p1!=NULL ) {
   3.346 +		if(pv_printf_s( msg, (pv_elem_p)p1, &dsp_s)!=0)
   3.347 +			return -1;
   3.348 +		dsp = &dsp_s;
   3.349 +	}
   3.350 +
   3.351 +	/* compute the URI string; if empty string -> make it NULL */
   3.352 +	if (pv_printf_s( msg, (pv_elem_p)p2, &uri_s)!=0)
   3.353 +		return -1;
   3.354 +	uri = uri_s.len?&uri_s:NULL;
   3.355 +
   3.356 +	if (parse_from_header(msg)<0 ) {
   3.357 +		LM_ERR("failed to find/parse FROM hdr\n");
   3.358 +		return -1;
   3.359 +	}
   3.360 +
   3.361 +	LM_DBG("dsp=%p (len=%d) , uri=%p (len=%d)\n",
   3.362 +		dsp,dsp?dsp->len:0,uri,uri?uri->len:0);
   3.363 +
   3.364 +	return (replace_uri(msg, dsp, uri, msg->from, &rr_from_param)==0)?1:-1;
   3.365 +}
   3.366 +
   3.367 +
   3.368 +static int w_restore_to(struct sip_msg *msg)
   3.369 +{
   3.370 +	/* safety checks - must be a request */
   3.371 +	if (msg->first_line.type!=SIP_REQUEST) {
   3.372 +		LM_ERR("called for something not request\n");
   3.373 +		return -1;
   3.374 +	}
   3.375 +
   3.376 +	return (restore_uri(msg,&rr_to_param,0)==0)?1:-1;
   3.377 +}
   3.378 +
   3.379 +
   3.380 +static int w_replace_to(struct sip_msg* msg, char* p1, char* p2)
   3.381 +{
   3.382 +	str uri_s;
   3.383 +	str dsp_s;
   3.384 +	str *uri;
   3.385 +	str *dsp;
   3.386 +
   3.387 +	if (p2==NULL) {
   3.388 +		p2 = p1;
   3.389 +		p1 = NULL;
   3.390 +		dsp = NULL;
   3.391 +	}
   3.392 +
   3.393 +	/* p1 dispaly , p2 uri */
   3.394 +
   3.395 +	if ( p1!=NULL ) {
   3.396 +		if(pv_printf_s( msg, (pv_elem_p)p1, &dsp_s)!=0)
   3.397 +			return -1;
   3.398 +		dsp = &dsp_s;
   3.399 +	}
   3.400 +
   3.401 +	/* compute the URI string; if empty string -> make it NULL */
   3.402 +	if (pv_printf_s( msg, (pv_elem_p)p2, &uri_s)!=0)
   3.403 +		return -1;
   3.404 +	uri = uri_s.len?&uri_s:NULL;
   3.405 +
   3.406 +	/* parse TO hdr */
   3.407 +	if ( msg->to==0 && (parse_headers(msg,HDR_TO_F,0)!=0 || msg->to==0) ) {
   3.408 +		LM_ERR("failed to parse TO hdr\n");
   3.409 +		return -1;
   3.410 +	}
   3.411 +
   3.412 +	return (replace_uri(msg, dsp, uri, msg->to, &rr_to_param)==0)?1:-1;
   3.413 +}
   3.414 +
   3.415 +
   3.416 +
   3.417 +
   3.418 +static int w_uac_auth(struct sip_msg* msg, char* str, char* str2)
   3.419 +{
   3.420 +	return (uac_auth(msg)==0)?1:-1;
   3.421 +}
   3.422 +
   3.423 +
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/opensips/scripts/db_berkeley/opensips/gw	Wed Feb 10 21:14:04 2010 +0100
     4.3 @@ -0,0 +1,10 @@
     4.4 +METADATA_COLUMNS
     4.5 +id(int) gw_name(str) grp_id(int) ip_addr(str) port(int) uri_scheme(int) transport(int) strip(int) tag(str) flags(int)
     4.6 +METADATA_KEY
     4.7 +1 
     4.8 +METADATA_READONLY
     4.9 +0
    4.10 +METADATA_LOGFLAGS
    4.11 +0
    4.12 +METADATA_DEFAULTS
    4.13 +NIL|NIL|NIL|NIL|NIL|NIL|NIL|NIL|NULL|0
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/opensips/scripts/dbtext/opensips/gw	Wed Feb 10 21:14:04 2010 +0100
     5.3 @@ -0,0 +1,1 @@
     5.4 +id(int,auto) gw_name(string) grp_id(int) ip_addr(string) port(int,null) uri_scheme(int,null) transport(int,null) strip(int,null) tag(string,null) flags(int) 
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/opensips/scripts/mysql/lcr-create.sql	Wed Feb 10 21:14:04 2010 +0100
     6.3 @@ -0,0 +1,30 @@
     6.4 +INSERT INTO version (table_name, table_version) values ('gw','8');
     6.5 +CREATE TABLE gw (
     6.6 +    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
     6.7 +    gw_name CHAR(128) NOT NULL,
     6.8 +    grp_id INT UNSIGNED NOT NULL,
     6.9 +    ip_addr CHAR(15) NOT NULL,
    6.10 +    port SMALLINT UNSIGNED,
    6.11 +    uri_scheme TINYINT UNSIGNED,
    6.12 +    transport TINYINT UNSIGNED,
    6.13 +    strip TINYINT UNSIGNED,
    6.14 +    tag CHAR(16) DEFAULT NULL,
    6.15 +    flags INT UNSIGNED DEFAULT 0 NOT NULL,
    6.16 +    CONSTRAINT gw_name_idx UNIQUE (gw_name)
    6.17 +) ENGINE=MyISAM;
    6.18 +
    6.19 +CREATE INDEX grp_id_idx ON gw (grp_id);
    6.20 +
    6.21 +INSERT INTO version (table_name, table_version) values ('lcr','3');
    6.22 +CREATE TABLE lcr (
    6.23 +    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
    6.24 +    prefix CHAR(16) DEFAULT NULL,
    6.25 +    from_uri CHAR(64) DEFAULT NULL,
    6.26 +    grp_id INT UNSIGNED NOT NULL,
    6.27 +    priority INT UNSIGNED NOT NULL
    6.28 +) ENGINE=MyISAM;
    6.29 +
    6.30 +CREATE INDEX prefix_idx ON lcr (prefix);
    6.31 +CREATE INDEX from_uri_idx ON lcr (from_uri);
    6.32 +CREATE INDEX grp_id_idx ON lcr (grp_id);
    6.33 +
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/opensips/scripts/oracle/lcr-create.sql	Wed Feb 10 21:14:04 2010 +0100
     7.3 @@ -0,0 +1,46 @@
     7.4 +INSERT INTO version (table_name, table_version) values ('gw','8');
     7.5 +CREATE TABLE gw (
     7.6 +    id NUMBER(10) PRIMARY KEY,
     7.7 +    gw_name VARCHAR2(128),
     7.8 +    grp_id NUMBER(10),
     7.9 +    ip_addr VARCHAR2(15),
    7.10 +    port NUMBER(5),
    7.11 +    uri_scheme NUMBER(5),
    7.12 +    transport NUMBER(5),
    7.13 +    strip NUMBER(5),
    7.14 +    tag VARCHAR2(16) DEFAULT NULL,
    7.15 +    flags NUMBER(10) DEFAULT 0 NOT NULL,
    7.16 +    CONSTRAINT gw_gw_name_idx  UNIQUE (gw_name)
    7.17 +);
    7.18 +
    7.19 +CREATE OR REPLACE TRIGGER gw_tr
    7.20 +before insert on gw FOR EACH ROW
    7.21 +BEGIN
    7.22 +  auto_id(:NEW.id);
    7.23 +END gw_tr;
    7.24 +/
    7.25 +BEGIN map2users('gw'); END;
    7.26 +/
    7.27 +CREATE INDEX gw_grp_id_idx  ON gw (grp_id);
    7.28 +
    7.29 +INSERT INTO version (table_name, table_version) values ('lcr','3');
    7.30 +CREATE TABLE lcr (
    7.31 +    id NUMBER(10) PRIMARY KEY,
    7.32 +    prefix VARCHAR2(16) DEFAULT NULL,
    7.33 +    from_uri VARCHAR2(64) DEFAULT NULL,
    7.34 +    grp_id NUMBER(10),
    7.35 +    priority NUMBER(10)
    7.36 +);
    7.37 +
    7.38 +CREATE OR REPLACE TRIGGER lcr_tr
    7.39 +before insert on lcr FOR EACH ROW
    7.40 +BEGIN
    7.41 +  auto_id(:NEW.id);
    7.42 +END lcr_tr;
    7.43 +/
    7.44 +BEGIN map2users('lcr'); END;
    7.45 +/
    7.46 +CREATE INDEX lcr_prefix_idx  ON lcr (prefix);
    7.47 +CREATE INDEX lcr_from_uri_idx  ON lcr (from_uri);
    7.48 +CREATE INDEX lcr_grp_id_idx  ON lcr (grp_id);
    7.49 +
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/opensips/scripts/postgres/lcr-create.sql	Wed Feb 10 21:14:04 2010 +0100
     8.3 @@ -0,0 +1,30 @@
     8.4 +INSERT INTO version (table_name, table_version) values ('gw','8');
     8.5 +CREATE TABLE gw (
     8.6 +    id SERIAL PRIMARY KEY NOT NULL,
     8.7 +    gw_name VARCHAR(128) NOT NULL,
     8.8 +    grp_id INTEGER NOT NULL,
     8.9 +    ip_addr VARCHAR(15) NOT NULL,
    8.10 +    port SMALLINT,
    8.11 +    uri_scheme SMALLINT,
    8.12 +    transport SMALLINT,
    8.13 +    strip SMALLINT,
    8.14 +    tag VARCHAR(16) DEFAULT NULL,
    8.15 +    flags INTEGER DEFAULT 0 NOT NULL,
    8.16 +    CONSTRAINT gw_gw_name_idx UNIQUE (gw_name)
    8.17 +);
    8.18 +
    8.19 +CREATE INDEX gw_grp_id_idx ON gw (grp_id);
    8.20 +
    8.21 +INSERT INTO version (table_name, table_version) values ('lcr','3');
    8.22 +CREATE TABLE lcr (
    8.23 +    id SERIAL PRIMARY KEY NOT NULL,
    8.24 +    prefix VARCHAR(16) DEFAULT NULL,
    8.25 +    from_uri VARCHAR(64) DEFAULT NULL,
    8.26 +    grp_id INTEGER NOT NULL,
    8.27 +    priority INTEGER NOT NULL
    8.28 +);
    8.29 +
    8.30 +CREATE INDEX lcr_prefix_idx ON lcr (prefix);
    8.31 +CREATE INDEX lcr_from_uri_idx ON lcr (from_uri);
    8.32 +CREATE INDEX lcr_grp_id_idx ON lcr (grp_id);
    8.33 +

mercurial