opensips/modules/lcr/lcr_mod.c

Wed, 10 Feb 2010 21:21:24 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 10 Feb 2010 21:21:24 +0100
changeset 17
733187d496d0
parent 16
c5c55937e44c
permissions
-rw-r--r--

Introduce authentication credential logic into the LCR module.
This logic is meant to complement that of changeset 18, adding
additional authentication flexibility to the UAC module.

michael@16 1 /*
michael@16 2 * $Id: lcr_mod.c 6015 2009-08-22 21:45:06Z bogdan_iancu $
michael@16 3 *
michael@16 4 * Least Cost Routing module (also implements sequential forking)
michael@16 5 *
michael@16 6 * Copyright (C) 2005 Juha Heinanen
michael@16 7 * Copyright (C) 2006 Voice Sistem SRL
michael@16 8 *
michael@16 9 * This file is part of opensips, a free SIP server.
michael@16 10 *
michael@16 11 * opensips is free software; you can redistribute it and/or modify
michael@16 12 * it under the terms of the GNU General Public License as published by
michael@16 13 * the Free Software Foundation; either version 2 of the License, or
michael@16 14 * (at your option) any later version
michael@16 15 *
michael@16 16 * opensips is distributed in the hope that it will be useful,
michael@16 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
michael@16 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
michael@16 19 * GNU General Public License for more details.
michael@16 20 *
michael@16 21 * You should have received a copy of the GNU General Public License
michael@16 22 * along with this program; if not, write to the Free Software
michael@16 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
michael@16 24 *
michael@16 25 * History:
michael@16 26 * -------
michael@16 27 * 2005-02-14: Introduced lcr module (jh)
michael@16 28 * 2005-02-20: Added sequential forking functions (jh)
michael@16 29 * 2005-02-25: Added support for int AVP names, combined addr and port
michael@16 30 * AVPs (jh)
michael@16 31 * 2005-07-28: Added support for gw URI scheme and transport,
michael@16 32 * backport from ser (kd)
michael@16 33 * 2005-08-20: Added support for gw prefixes (jh)
michael@16 34 * 2005-09-03: Request-URI user part can be modified between load_gws()
michael@16 35 * and first next_gw() calls.
michael@16 36 */
michael@16 37
michael@16 38 #include <stdio.h>
michael@16 39 #include <stdlib.h>
michael@16 40 #include <string.h>
michael@16 41 #include <sys/types.h>
michael@16 42 #include <sys/socket.h>
michael@16 43 #include <netinet/in.h>
michael@16 44 #include <arpa/inet.h>
michael@16 45 #include <regex.h>
michael@16 46 #include "../../sr_module.h"
michael@16 47 #include "../../dprint.h"
michael@16 48 #include "../../ut.h"
michael@16 49 #include "../../error.h"
michael@16 50 #include "../../mem/mem.h"
michael@16 51 #include "../../mem/shm_mem.h"
michael@16 52 #include "../../db/db.h"
michael@16 53 #include "../../usr_avp.h"
michael@16 54 #include "../../parser/parse_uri.h"
michael@16 55 #include "../../parser/parse_from.h"
michael@16 56 #include "../../parser/msg_parser.h"
michael@16 57 #include "../../action.h"
michael@16 58 #include "../../qvalue.h"
michael@16 59 #include "../../dset.h"
michael@16 60 #include "../../ip_addr.h"
michael@16 61 #include "../../resolve.h"
michael@16 62 #include "../../mi/mi.h"
michael@16 63 #include "../../mod_fix.h"
michael@16 64 #include "../../socket_info.h"
michael@16 65 #include "../../pvar.h"
michael@16 66 #include "../../mod_fix.h"
michael@16 67 #include "mi.h"
michael@16 68
michael@16 69
michael@16 70
michael@16 71 /*
michael@16 72 * Version of gw and lcr tables required by the module,
michael@16 73 * increment this value if you change the table in
michael@16 74 * an backwards incompatible way
michael@16 75 */
michael@16 76 #define GW_TABLE_VERSION 8
michael@16 77 #define LCR_TABLE_VERSION 3
michael@16 78
michael@16 79 /* usr_avp flag for sequential forking */
michael@16 80 #define Q_FLAG (1<<2)
michael@16 81
michael@16 82 static void destroy(void); /* Module destroy function */
michael@16 83 static int mi_child_init(void);
michael@16 84 static int mod_init(void); /* Module initialization function */
michael@16 85 static int fixstringloadgws(void **param, int param_count);
michael@16 86
michael@16 87 int reload_gws ( void );
michael@16 88
michael@16 89 #define GW_TABLE "gw"
michael@16 90
michael@16 91 #define GW_NAME_COL "gw_name"
michael@16 92
michael@16 93 #define GRP_ID_COL "grp_id"
michael@16 94
michael@16 95 #define IP_ADDR_COL "ip_addr"
michael@16 96
michael@16 97 #define PORT_COL "port"
michael@16 98
michael@16 99 #define URI_SCHEME_COL "uri_scheme"
michael@16 100
michael@16 101 #define TRANSPORT_COL "transport"
michael@16 102
michael@16 103 #define STRIP_COL "strip"
michael@16 104
michael@16 105 #define TAG_COL "tag"
michael@16 106
michael@16 107 #define FLAGS_COL "flags"
michael@16 108
michael@16 109 #define LCR_TABLE "lcr"
michael@16 110
michael@16 111 #define PREFIX_COL "prefix"
michael@16 112
michael@16 113 #define FROM_URI_COL "from_uri"
michael@16 114
michael@16 115 #define PRIORITY_COL "priority"
michael@16 116
michael@17 117 #define USER_COL "user"
michael@17 118
michael@17 119 #define REALM_COL "realm"
michael@17 120
michael@17 121 #define PASSWD_COL "passwd"
michael@17 122
michael@16 123 #define MAX_NO_OF_GWS 32
michael@16 124 #define MAX_NO_OF_LCRS 256
michael@16 125 #define MAX_PREFIX_LEN 256
michael@17 126 #define MAX_USER_LEN 64
michael@17 127 #define MAX_REALM_LEN 64
michael@17 128 #define MAX_PASSWD_LEN 64
michael@16 129 #define MAX_TAG_LEN 16
michael@16 130 #define MAX_FROM_URI_LEN 256
michael@16 131
michael@16 132 /* Default module parameter values */
michael@16 133 #define DEF_FR_INV_TIMER 90
michael@16 134 #define DEF_FR_INV_TIMER_NEXT 30
michael@16 135 #define DEF_PREFIX_MODE 0
michael@16 136
michael@16 137 /*
michael@16 138 * Type definitions
michael@16 139 */
michael@16 140
michael@16 141 typedef enum sip_protos uri_transport;
michael@16 142
michael@16 143 struct gw_info {
michael@16 144 unsigned int ip_addr;
michael@16 145 unsigned int port;
michael@16 146 unsigned int grp_id;
michael@16 147 uri_type scheme;
michael@16 148 uri_transport transport;
michael@16 149 unsigned int strip;
michael@16 150 char tag[MAX_TAG_LEN + 1];
michael@16 151 unsigned short tag_len;
michael@16 152 unsigned int flags;
michael@17 153 char user[MAX_USER_LEN];
michael@17 154 unsigned short user_len;
michael@17 155 char realm[MAX_REALM_LEN];
michael@17 156 unsigned short realm_len;
michael@17 157 char passwd[MAX_PASSWD_LEN];
michael@17 158 unsigned short passwd_len;
michael@16 159 };
michael@16 160
michael@16 161 struct lcr_info {
michael@16 162 char prefix[MAX_PREFIX_LEN + 1];
michael@16 163 unsigned short prefix_len;
michael@16 164 char from_uri[MAX_FROM_URI_LEN + 1];
michael@16 165 unsigned short from_uri_len;
michael@16 166 unsigned int grp_id;
michael@16 167 unsigned short priority;
michael@16 168 unsigned short end_record;
michael@16 169 };
michael@16 170
michael@16 171 struct prefix_regex {
michael@16 172 regex_t re;
michael@16 173 short int valid;
michael@16 174 };
michael@16 175
michael@16 176 struct from_uri_regex {
michael@16 177 regex_t re;
michael@16 178 short int valid;
michael@16 179 };
michael@16 180
michael@16 181 struct mi {
michael@16 182 int gw_index;
michael@16 183 int route_index;
michael@16 184 int randomizer;
michael@16 185 };
michael@16 186
michael@16 187
michael@16 188 /*
michael@16 189 * Database variables
michael@16 190 */
michael@16 191 static db_con_t* db_handle = 0; /* Database connection handle */
michael@16 192 static db_func_t lcr_dbf;
michael@16 193
michael@16 194 /*
michael@16 195 * Module parameter variables
michael@16 196 */
michael@16 197
michael@16 198 /* database */
michael@16 199 static str db_url = str_init(DEFAULT_RODB_URL);
michael@16 200 static str gw_table = str_init(GW_TABLE);
michael@16 201 static str gw_name_col = str_init(GW_NAME_COL);
michael@16 202 static str grp_id_col = str_init(GRP_ID_COL);
michael@16 203 static str ip_addr_col = str_init(IP_ADDR_COL);
michael@16 204 static str port_col = str_init(PORT_COL);
michael@16 205 static str uri_scheme_col = str_init(URI_SCHEME_COL);
michael@16 206 static str transport_col = str_init(TRANSPORT_COL);
michael@16 207 static str strip_col = str_init(STRIP_COL);
michael@16 208 static str tag_col = str_init(TAG_COL);
michael@16 209 static str flags_col = str_init(FLAGS_COL);
michael@16 210 static str lcr_table = str_init(LCR_TABLE);
michael@16 211 static str prefix_col = str_init(PREFIX_COL);
michael@16 212 static str from_uri_col = str_init(FROM_URI_COL);
michael@16 213 static str priority_col = str_init(PRIORITY_COL);
michael@17 214 static str user_col = str_init(USER_COL);
michael@17 215 static str realm_col = str_init(REALM_COL);
michael@17 216 static str passwd_col = str_init(PASSWD_COL);
michael@16 217
michael@16 218 /* timer */
michael@16 219 int fr_inv_timer = DEF_FR_INV_TIMER;
michael@16 220 int fr_inv_timer_next = DEF_FR_INV_TIMER_NEXT;
michael@16 221
michael@16 222 /* avps */
michael@16 223 static char *fr_inv_timer_avp_param = NULL;
michael@16 224 static char *gw_uri_avp_param = NULL;
michael@16 225 static char *ruri_user_avp_param = NULL;
michael@16 226 static char *contact_avp_param = NULL;
michael@16 227 static char *rpid_avp_param = NULL;
michael@16 228 static char *flags_avp_param = NULL;
michael@17 229 static char *user_avp_param = NULL;
michael@17 230 static char *realm_avp_param = NULL;
michael@17 231 static char *passwd_avp_param = NULL;
michael@16 232
michael@16 233 /* prefix mode */
michael@16 234 int prefix_mode_param = DEF_PREFIX_MODE;
michael@16 235
michael@16 236 /*
michael@16 237 * Other module types and variables
michael@16 238 */
michael@16 239
michael@16 240 struct contact {
michael@16 241 str uri;
michael@16 242 qvalue_t q;
michael@16 243 str dst_uri;
michael@16 244 str path;
michael@16 245 unsigned int flags;
michael@16 246 struct socket_info* sock;
michael@16 247 unsigned short q_flag;
michael@16 248 struct contact *next;
michael@16 249 };
michael@16 250
michael@16 251 static int fr_inv_timer_avp_type;
michael@16 252 static int_str fr_inv_timer_avp;
michael@16 253 static int gw_uri_avp_type;
michael@16 254 static int_str gw_uri_avp;
michael@16 255 static int ruri_user_avp_type;
michael@16 256 static int_str ruri_user_avp;
michael@16 257 static int contact_avp_type;
michael@16 258 static int_str contact_avp;
michael@16 259 static int rpid_avp_type;
michael@16 260 static int_str rpid_avp;
michael@16 261 static int flags_avp_type;
michael@16 262 static int_str flags_avp;
michael@17 263 static int user_avp_type;
michael@17 264 static int_str user_avp;
michael@17 265 static int realm_avp_type;
michael@17 266 static int_str realm_avp;
michael@17 267 static int passwd_avp_type;
michael@17 268 static int_str passwd_avp;
michael@16 269
michael@16 270 struct gw_info **gws; /* Pointer to current gw table pointer */
michael@16 271 struct gw_info *gws_1; /* Pointer to gw table 1 */
michael@16 272 struct gw_info *gws_2; /* Pointer to gw table 2 */
michael@16 273
michael@16 274 struct lcr_info **lcrs; /* Pointer to current lcr table pointer */
michael@16 275 struct lcr_info *lcrs_1; /* Pointer to lcr table 1 */
michael@16 276 struct lcr_info *lcrs_2; /* Pointer to lcr table 2 */
michael@16 277
michael@16 278 unsigned int *lcrs_ws_reload_counter;
michael@16 279 unsigned int reload_counter;
michael@16 280
michael@16 281 struct prefix_regex prefix_reg[MAX_NO_OF_LCRS];
michael@16 282 struct from_uri_regex from_uri_reg[MAX_NO_OF_LCRS];
michael@16 283
michael@16 284 /*
michael@16 285 * Module functions that are defined later
michael@16 286 */
michael@16 287 static int load_gws_0(struct sip_msg* _m, char* _s1, char* _s2);
michael@16 288 static int load_gws_1(struct sip_msg* _m, char* _s1, char* _s2);
michael@16 289 static int load_gws_from_grp(struct sip_msg* _m, char* _s1, char* _s2);
michael@16 290 static int next_gw(struct sip_msg* _m, char* _s1, char* _s2);
michael@16 291 static int from_gw_0(struct sip_msg* _m, char* _s1, char* _s2);
michael@16 292 static int from_gw_1(struct sip_msg* _m, char* _s1, char* _s2);
michael@16 293 static int from_gw_grp(struct sip_msg* _m, char* _s1, char* _s2);
michael@16 294 static int to_gw(struct sip_msg* _m, char* _s1, char* _s2);
michael@16 295 static int to_gw_grp(struct sip_msg* _m, char* _s1, char* _s2);
michael@16 296 static int load_contacts (struct sip_msg*, char*, char*);
michael@16 297 static int next_contacts (struct sip_msg*, char*, char*);
michael@16 298
michael@16 299
michael@16 300 /*
michael@16 301 * Exported functions
michael@16 302 */
michael@16 303 static cmd_export_t cmds[] = {
michael@16 304 {"load_gws", (cmd_function)load_gws_0, 0, 0, 0, REQUEST_ROUTE},
michael@16 305 {"load_gws", (cmd_function)load_gws_1, 1, fixup_pvar_null,
michael@16 306 fixup_free_pvar_null, REQUEST_ROUTE},
michael@16 307 {"load_gws_from_grp", (cmd_function)load_gws_from_grp, 1,
michael@16 308 fixstringloadgws, 0, REQUEST_ROUTE},
michael@16 309 {"next_gw", (cmd_function)next_gw, 0, 0, 0,
michael@16 310 REQUEST_ROUTE | FAILURE_ROUTE},
michael@16 311 {"from_gw", (cmd_function)from_gw_0, 0, 0, 0,
michael@16 312 REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE},
michael@16 313 {"from_gw", (cmd_function)from_gw_1, 1, fixup_pvar_null,
michael@16 314 fixup_free_pvar_null, REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE},
michael@16 315 {"from_gw_grp", (cmd_function)from_gw_grp, 1, fixup_uint_null, 0,
michael@16 316 REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE},
michael@16 317 {"to_gw", (cmd_function)to_gw, 0, 0, 0,
michael@16 318 REQUEST_ROUTE | FAILURE_ROUTE},
michael@16 319 {"to_gw", (cmd_function)to_gw_grp, 1, fixup_uint_null, 0,
michael@16 320 REQUEST_ROUTE | FAILURE_ROUTE},
michael@16 321 {"load_contacts", (cmd_function)load_contacts, 0, 0, 0,
michael@16 322 REQUEST_ROUTE},
michael@16 323 {"next_contacts", (cmd_function)next_contacts, 0, 0, 0,
michael@16 324 REQUEST_ROUTE | FAILURE_ROUTE},
michael@16 325 {0, 0, 0, 0, 0, 0}
michael@16 326 };
michael@16 327
michael@16 328
michael@16 329 /*
michael@16 330 * Exported parameters
michael@16 331 */
michael@16 332 static param_export_t params[] = {
michael@16 333 {"db_url", STR_PARAM, &db_url.s },
michael@16 334 {"gw_table", STR_PARAM, &gw_table.s },
michael@16 335 {"gw_name_column", STR_PARAM, &gw_name_col.s },
michael@16 336 {"grp_id_column", STR_PARAM, &grp_id_col.s },
michael@16 337 {"ip_addr_column", STR_PARAM, &ip_addr_col.s },
michael@16 338 {"port_column", STR_PARAM, &port_col.s },
michael@16 339 {"uri_scheme_column", STR_PARAM, &uri_scheme_col.s },
michael@16 340 {"transport_column", STR_PARAM, &transport_col.s },
michael@16 341 {"strip_column", STR_PARAM, &strip_col.s },
michael@16 342 {"tag_column", STR_PARAM, &tag_col.s },
michael@16 343 {"flags_column", STR_PARAM, &flags_col.s },
michael@16 344 {"lcr_table", STR_PARAM, &lcr_table.s },
michael@16 345 {"prefix_column", STR_PARAM, &prefix_col.s },
michael@16 346 {"from_uri_column", STR_PARAM, &from_uri_col.s },
michael@16 347 {"priority_column", STR_PARAM, &priority_col.s },
michael@16 348 {"fr_inv_timer_avp", STR_PARAM, &fr_inv_timer_avp_param },
michael@16 349 {"gw_uri_avp", STR_PARAM, &gw_uri_avp_param },
michael@16 350 {"ruri_user_avp", STR_PARAM, &ruri_user_avp_param },
michael@16 351 {"contact_avp", STR_PARAM, &contact_avp_param },
michael@16 352 {"rpid_avp", STR_PARAM, &rpid_avp_param },
michael@16 353 {"flags_avp", STR_PARAM, &flags_avp_param },
michael@16 354 {"fr_inv_timer", INT_PARAM, &fr_inv_timer },
michael@16 355 {"fr_inv_timer_next", INT_PARAM, &fr_inv_timer_next },
michael@16 356 {"prefix_mode", INT_PARAM, &prefix_mode_param },
michael@17 357 {"user_column", STR_PARAM, &user_col.s },
michael@17 358 {"realm_column", STR_PARAM, &realm_col.s },
michael@17 359 {"passwd_column", STR_PARAM, &passwd_col.s },
michael@17 360 {"auth_username_avp", STR_PARAM, &user_avp_param },
michael@17 361 {"auth_realm_avp", STR_PARAM, &realm_avp_param },
michael@17 362 {"auth_password_avp", STR_PARAM, &passwd_avp_param },
michael@16 363 {0, 0, 0}
michael@16 364 };
michael@16 365
michael@16 366
michael@16 367 /*
michael@16 368 * Exported MI functions
michael@16 369 */
michael@16 370 static mi_export_t mi_cmds[] = {
michael@16 371 { MI_LCR_RELOAD, mi_lcr_reload, MI_NO_INPUT_FLAG, 0, mi_child_init },
michael@16 372 { MI_LCR_DUMP, mi_lcr_dump, MI_NO_INPUT_FLAG, 0, 0 },
michael@16 373 { 0, 0, 0, 0 ,0}
michael@16 374 };
michael@16 375
michael@16 376
michael@16 377 /*
michael@16 378 * Module interface
michael@16 379 */
michael@16 380 struct module_exports exports = {
michael@16 381 "lcr",
michael@16 382 MODULE_VERSION,
michael@16 383 DEFAULT_DLFLAGS, /* dlopen flags */
michael@16 384 cmds, /* Exported functions */
michael@16 385 params, /* Exported parameters */
michael@16 386 0, /* exported statistics */
michael@16 387 mi_cmds, /* exported MI functions */
michael@16 388 0, /* exported pseudo-variables */
michael@16 389 0, /* extra processes */
michael@16 390 mod_init, /* module initialization function */
michael@16 391 0, /* response function */
michael@16 392 destroy, /* destroy function */
michael@16 393 0 /* child initialization function */
michael@16 394 };
michael@16 395
michael@16 396
michael@16 397 static int lcr_db_init(const str* db_url)
michael@16 398 {
michael@16 399 if (lcr_dbf.init==0){
michael@16 400 LM_CRIT("Null lcr_dbf\n");
michael@16 401 goto error;
michael@16 402 }
michael@16 403 db_handle=lcr_dbf.init(db_url);
michael@16 404 if (db_handle==0){
michael@16 405 LM_ERR("Unable to connect to the database\n");
michael@16 406 goto error;
michael@16 407 }
michael@16 408 return 0;
michael@16 409 error:
michael@16 410 return -1;
michael@16 411 }
michael@16 412
michael@16 413
michael@16 414
michael@16 415 static int lcr_db_bind(const str* db_url)
michael@16 416 {
michael@16 417 if (db_bind_mod(db_url, &lcr_dbf)<0){
michael@16 418 LM_ERR("Unable to bind to the database module\n");
michael@16 419 return -1;
michael@16 420 }
michael@16 421
michael@16 422 if (!DB_CAPABILITY(lcr_dbf, DB_CAP_QUERY)) {
michael@16 423 LM_ERR("Database module does not implement 'query' function\n");
michael@16 424 return -1;
michael@16 425 }
michael@16 426
michael@16 427 return 0;
michael@16 428 }
michael@16 429
michael@16 430
michael@16 431 static void lcr_db_close(void)
michael@16 432 {
michael@16 433 if (db_handle && lcr_dbf.close){
michael@16 434 lcr_dbf.close(db_handle);
michael@16 435 db_handle=0;
michael@16 436 }
michael@16 437 }
michael@16 438
michael@16 439
michael@16 440 static int mi_child_init(void)
michael@16 441 {
michael@16 442 return lcr_db_init(&db_url);
michael@16 443 }
michael@16 444
michael@16 445
michael@16 446 /*
michael@16 447 * Module initialization function that is called before the main process forks
michael@16 448 */
michael@16 449 static int mod_init(void)
michael@16 450 {
michael@16 451 int i;
michael@16 452 pv_spec_t avp_spec;
michael@16 453 str s;
michael@16 454 unsigned short avp_flags;
michael@16 455
michael@16 456 LM_DBG("Initializing\n");
michael@16 457
michael@16 458 /* Update length of module variables */
michael@16 459 db_url.len = strlen(db_url.s);
michael@16 460 gw_table.len = strlen(gw_table.s);
michael@16 461 gw_name_col.len = strlen(gw_name_col.s);
michael@16 462 grp_id_col.len = strlen(grp_id_col.s);
michael@16 463 ip_addr_col.len = strlen(ip_addr_col.s);
michael@16 464 port_col.len = strlen(port_col.s);
michael@16 465 uri_scheme_col.len = strlen(uri_scheme_col.s);
michael@16 466 transport_col.len = strlen(transport_col.s);
michael@16 467 strip_col.len = strlen(strip_col.s);
michael@16 468 tag_col.len = strlen(tag_col.s);
michael@16 469 flags_col.len = strlen(flags_col.s);
michael@16 470 lcr_table.len = strlen(lcr_table.s);
michael@16 471 prefix_col.len = strlen(prefix_col.s);
michael@16 472 from_uri_col.len = strlen(from_uri_col.s);
michael@16 473 priority_col.len = strlen(priority_col.s);
michael@17 474 user_col.len = strlen(user_col.s);
michael@17 475 realm_col.len = strlen(realm_col.s);
michael@17 476 passwd_col.len = strlen(passwd_col.s);
michael@16 477
michael@16 478 /* Bind database */
michael@16 479 if (lcr_db_bind(&db_url)) {
michael@16 480 LM_ERR("No database module found\n");
michael@16 481 return -1;
michael@16 482 }
michael@16 483
michael@16 484 /* Check value of prefix_mode */
michael@16 485 if ((prefix_mode_param != 0) && (prefix_mode_param != 1)) {
michael@16 486 LM_ERR("Invalid prefix_mode value <%d>\n", prefix_mode_param);
michael@16 487 return -1;
michael@16 488 }
michael@16 489
michael@16 490 /* Process AVP params */
michael@16 491 if (fr_inv_timer_avp_param && *fr_inv_timer_avp_param) {
michael@16 492 s.s = fr_inv_timer_avp_param; s.len = strlen(s.s);
michael@16 493 if (pv_parse_spec(&s, &avp_spec)==0
michael@16 494 || avp_spec.type!=PVT_AVP) {
michael@16 495 LM_ERR("Malformed or non AVP definition <%s>\n",
michael@16 496 fr_inv_timer_avp_param);
michael@16 497 return -1;
michael@16 498 }
michael@16 499
michael@16 500 if(pv_get_avp_name(0, &(avp_spec.pvp), &fr_inv_timer_avp, &avp_flags)!=0) {
michael@16 501 LM_ERR("Invalid AVP definition <%s>\n", fr_inv_timer_avp_param);
michael@16 502 return -1;
michael@16 503 }
michael@16 504 fr_inv_timer_avp_type = avp_flags;
michael@16 505 } else {
michael@16 506 LM_ERR("AVP fr_inv_timer_avp has not been defined\n");
michael@16 507 return -1;
michael@16 508 }
michael@16 509
michael@16 510 if (gw_uri_avp_param && *gw_uri_avp_param) {
michael@16 511 s.s = gw_uri_avp_param; s.len = strlen(s.s);
michael@16 512 if (pv_parse_spec(&s, &avp_spec)==0
michael@16 513 || avp_spec.type!=PVT_AVP) {
michael@16 514 LM_ERR("Malformed or non AVP definition <%s>\n", gw_uri_avp_param);
michael@16 515 return -1;
michael@16 516 }
michael@16 517
michael@16 518 if(pv_get_avp_name(0, &(avp_spec.pvp), &gw_uri_avp, &avp_flags)!=0) {
michael@16 519 LM_ERR("Invalid AVP definition <%s>\n", gw_uri_avp_param);
michael@16 520 return -1;
michael@16 521 }
michael@16 522 gw_uri_avp_type = avp_flags;
michael@16 523 } else {
michael@16 524 LM_ERR("AVP gw_uri_avp has not been defined\n");
michael@16 525 return -1;
michael@16 526 }
michael@16 527
michael@16 528 if (ruri_user_avp_param && *ruri_user_avp_param) {
michael@16 529 s.s = ruri_user_avp_param; s.len = strlen(s.s);
michael@16 530 if (pv_parse_spec(&s, &avp_spec)==0
michael@16 531 || avp_spec.type!=PVT_AVP) {
michael@16 532 LM_ERR("Malformed or non AVP definition <%s>\n",
michael@16 533 ruri_user_avp_param);
michael@16 534 return -1;
michael@16 535 }
michael@16 536
michael@16 537 if(pv_get_avp_name(0, &(avp_spec.pvp), &ruri_user_avp, &avp_flags)!=0) {
michael@16 538 LM_ERR("Invalid AVP definition <%s>\n", ruri_user_avp_param);
michael@16 539 return -1;
michael@16 540 }
michael@16 541 ruri_user_avp_type = avp_flags;
michael@16 542 } else {
michael@16 543 LM_ERR("AVP ruri_user_avp has not been defined\n");
michael@16 544 return -1;
michael@16 545 }
michael@16 546
michael@16 547 if (contact_avp_param && *contact_avp_param) {
michael@16 548 s.s = contact_avp_param; s.len = strlen(s.s);
michael@16 549 if (pv_parse_spec(&s, &avp_spec)==0
michael@16 550 || avp_spec.type!=PVT_AVP) {
michael@16 551 LM_ERR("Malformed or non AVP definition <%s>\n",
michael@16 552 contact_avp_param);
michael@16 553 return -1;
michael@16 554 }
michael@16 555
michael@16 556 if(pv_get_avp_name(0, &(avp_spec.pvp), &contact_avp, &avp_flags)!=0) {
michael@16 557 LM_ERR("Invalid AVP definition <%s>\n", contact_avp_param);
michael@16 558 return -1;
michael@16 559 }
michael@16 560 contact_avp_type = avp_flags;
michael@16 561 } else {
michael@16 562 LM_ERR("AVP contact_avp has not been defined\n");
michael@16 563 return -1;
michael@16 564 }
michael@16 565
michael@16 566 if (rpid_avp_param && *rpid_avp_param) {
michael@16 567 s.s = rpid_avp_param; s.len = strlen(s.s);
michael@16 568 if (pv_parse_spec(&s, &avp_spec)==0
michael@16 569 || avp_spec.type!=PVT_AVP) {
michael@16 570 LM_ERR("Malformed or non AVP definition <%s>\n", rpid_avp_param);
michael@16 571 return -1;
michael@16 572 }
michael@16 573
michael@16 574 if(pv_get_avp_name(0, &(avp_spec.pvp), &rpid_avp, &avp_flags)!=0) {
michael@16 575 LM_ERR("Invalid AVP definition <%s>\n", rpid_avp_param);
michael@16 576 return -1;
michael@16 577 }
michael@16 578 rpid_avp_type = avp_flags;
michael@16 579 } else {
michael@16 580 LM_ERR("AVP rpid_avp has not been defined\n");
michael@16 581 return -1;
michael@16 582 }
michael@16 583
michael@16 584 if (flags_avp_param && *flags_avp_param) {
michael@16 585 s.s = flags_avp_param; s.len = strlen(s.s);
michael@16 586 if (pv_parse_spec(&s, &avp_spec)==0
michael@16 587 || avp_spec.type!=PVT_AVP) {
michael@16 588 LM_ERR("Malformed or non AVP definition <%s>\n", flags_avp_param);
michael@16 589 return -1;
michael@16 590 }
michael@16 591
michael@16 592 if(pv_get_avp_name(0, &(avp_spec.pvp), &flags_avp, &avp_flags)!=0) {
michael@16 593 LM_ERR("Invalid AVP definition <%s>\n", flags_avp_param);
michael@16 594 return -1;
michael@16 595 }
michael@16 596 flags_avp_type = avp_flags;
michael@16 597 } else {
michael@16 598 LM_ERR("AVP flags_avp has not been defined\n");
michael@16 599 return -1;
michael@16 600 }
michael@16 601
michael@17 602 if (user_avp_param && *user_avp_param) {
michael@17 603 s.s = user_avp_param; s.len = strlen(s.s);
michael@17 604 if (pv_parse_spec(&s, &avp_spec)==0
michael@17 605 || avp_spec.type!=PVT_AVP) {
michael@17 606 LM_ERR("Malformed or non AVP definition <%s>\n", user_avp_param);
michael@17 607 return -1;
michael@17 608 }
michael@17 609
michael@17 610 if(pv_get_avp_name(0, &(avp_spec.pvp), &user_avp, &avp_flags)!=0) {
michael@17 611 LM_ERR("Invalid AVP definition <%s>\n", user_avp_param);
michael@17 612 return -1;
michael@17 613 }
michael@17 614 user_avp_type = avp_flags;
michael@17 615 } else {
michael@17 616 LM_ERR("AVP user_avp has not been defined\n");
michael@17 617 return -1;
michael@17 618 }
michael@17 619
michael@17 620 if (realm_avp_param && *realm_avp_param) {
michael@17 621 s.s = realm_avp_param; s.len = strlen(s.s);
michael@17 622 if (pv_parse_spec(&s, &avp_spec)==0
michael@17 623 || avp_spec.type!=PVT_AVP) {
michael@17 624 LM_ERR("Malformed or non AVP definition <%s>\n", realm_avp_param);
michael@17 625 return -1;
michael@17 626 }
michael@17 627
michael@17 628 if(pv_get_avp_name(0, &(avp_spec.pvp), &realm_avp, &avp_flags)!=0) {
michael@17 629 LM_ERR("Invalid AVP definition <%s>\n", realm_avp_param);
michael@17 630 return -1;
michael@17 631 }
michael@17 632 realm_avp_type = avp_flags;
michael@17 633 } else {
michael@17 634 LM_ERR("AVP realm_avp has not been defined\n");
michael@17 635 return -1;
michael@17 636 }
michael@17 637
michael@17 638 if (passwd_avp_param && *passwd_avp_param) {
michael@17 639 s.s = passwd_avp_param; s.len = strlen(s.s);
michael@17 640 if (pv_parse_spec(&s, &avp_spec)==0
michael@17 641 || avp_spec.type!=PVT_AVP) {
michael@17 642 LM_ERR("Malformed or non AVP definition <%s>\n", passwd_avp_param);
michael@17 643 return -1;
michael@17 644 }
michael@17 645
michael@17 646 if(pv_get_avp_name(0, &(avp_spec.pvp), &passwd_avp, &avp_flags)!=0) {
michael@17 647 LM_ERR("Invalid AVP definition <%s>\n", passwd_avp_param);
michael@17 648 return -1;
michael@17 649 }
michael@17 650 passwd_avp_type = avp_flags;
michael@17 651 } else {
michael@17 652 LM_ERR("AVP passwd_avp has not been defined\n");
michael@17 653 return -1;
michael@17 654 }
michael@17 655
michael@16 656 /* Check table version */
michael@16 657 db_con_t* dbh;
michael@16 658 if (lcr_dbf.init==0){
michael@16 659 LM_CRIT("Unbound database\n");
michael@16 660 return -1;
michael@16 661 }
michael@16 662 dbh=lcr_dbf.init(&db_url);
michael@16 663 if (dbh==0){
michael@16 664 LM_ERR("Unable to open database connection\n");
michael@16 665 return -1;
michael@16 666 }
michael@16 667 if((db_check_table_version(&lcr_dbf, dbh, &gw_table, GW_TABLE_VERSION) < 0) ||
michael@16 668 (db_check_table_version(&lcr_dbf, dbh, &lcr_table, LCR_TABLE_VERSION) < 0)) {
michael@16 669 LM_ERR("error during table version check.\n");
michael@16 670 lcr_dbf.close(dbh);
michael@16 671 goto err;
michael@16 672 }
michael@16 673 lcr_dbf.close(dbh);
michael@16 674
michael@16 675 /* Initializing gw tables and gw table pointer variable */
michael@16 676 gws_1 = (struct gw_info *)shm_malloc(sizeof(struct gw_info) *
michael@16 677 (MAX_NO_OF_GWS + 1));
michael@16 678 if (gws_1 == 0) {
michael@16 679 LM_ERR("No memory for gw table\n");
michael@16 680 goto err;
michael@16 681 }
michael@16 682 gws_2 = (struct gw_info *)shm_malloc(sizeof(struct gw_info) *
michael@16 683 (MAX_NO_OF_GWS + 1));
michael@16 684 if (gws_2 == 0) {
michael@16 685 LM_ERR("No memory for gw table\n");
michael@16 686 goto err;
michael@16 687 }
michael@16 688 for (i = 0; i < MAX_NO_OF_GWS + 1; i++) {
michael@16 689 gws_1[i].ip_addr = gws_2[i].ip_addr = 0;
michael@16 690 }
michael@16 691 gws = (struct gw_info **)shm_malloc(sizeof(struct gw_info *));
michael@16 692 if (gws == 0) {
michael@16 693 LM_ERR("No memory for gw table pointer\n");
michael@16 694 }
michael@16 695 *gws = gws_1;
michael@16 696
michael@16 697 /* Initializing lcr tables and lcr table pointer variable */
michael@16 698 lcrs_1 = (struct lcr_info *)shm_malloc(sizeof(struct lcr_info) *
michael@16 699 (MAX_NO_OF_LCRS + 1));
michael@16 700 if (lcrs_1 == 0) {
michael@16 701 LM_ERR("No memory for lcr table\n");
michael@16 702 goto err;
michael@16 703 }
michael@16 704 lcrs_2 = (struct lcr_info *)shm_malloc(sizeof(struct lcr_info) *
michael@16 705 (MAX_NO_OF_LCRS + 1));
michael@16 706 if (lcrs_2 == 0) {
michael@16 707 LM_ERR("No memory for lcr table\n");
michael@16 708 goto err;
michael@16 709 }
michael@16 710 for (i = 0; i < MAX_NO_OF_LCRS + 1; i++) {
michael@16 711 lcrs_1[i].end_record = lcrs_2[i].end_record = 0;
michael@16 712 }
michael@16 713 lcrs = (struct lcr_info **)shm_malloc(sizeof(struct lcr_info *));
michael@16 714 if (lcrs == 0) {
michael@16 715 LM_ERR("No memory for lcr table pointer\n");
michael@16 716 goto err;
michael@16 717 }
michael@16 718 *lcrs = lcrs_1;
michael@16 719
michael@16 720 lcrs_ws_reload_counter = (unsigned int *)shm_malloc(sizeof(unsigned int));
michael@16 721 if (lcrs_ws_reload_counter == 0) {
michael@16 722 LM_ERR("No memory for reload counter\n");
michael@16 723 goto err;
michael@16 724 }
michael@16 725 *lcrs_ws_reload_counter = reload_counter = 0;
michael@16 726
michael@16 727 memset(prefix_reg, 0, sizeof(struct prefix_regex) * MAX_NO_OF_LCRS);
michael@16 728 memset(from_uri_reg, 0, sizeof(struct from_uri_regex) * MAX_NO_OF_LCRS);
michael@16 729
michael@16 730 /* First reload */
michael@16 731 if (reload_gws() == -1) {
michael@16 732 LM_CRIT("Failed to reload gateways and routes\n");
michael@16 733 goto err;
michael@16 734 }
michael@16 735
michael@16 736 return 0;
michael@16 737
michael@16 738 err:
michael@16 739 return -1;
michael@16 740 }
michael@16 741
michael@16 742
michael@16 743 static void destroy(void)
michael@16 744 {
michael@16 745 lcr_db_close();
michael@16 746 }
michael@16 747
michael@16 748 /*
michael@16 749 * Sort lcr records by prefix_len and priority.
michael@16 750 */
michael@16 751 static int comp_lcrs(const void *m1, const void *m2)
michael@16 752 {
michael@16 753 int result = -1;
michael@16 754
michael@16 755 struct mi *mi1 = (struct mi *) m1;
michael@16 756 struct mi *mi2 = (struct mi *) m2;
michael@16 757
michael@16 758 struct lcr_info lcr_record1 = (*lcrs)[mi1->route_index];
michael@16 759 struct lcr_info lcr_record2 = (*lcrs)[mi2->route_index];
michael@16 760
michael@16 761 if (prefix_mode_param == 0) {
michael@16 762 /* Sort by prefix. */
michael@16 763 if (lcr_record1.prefix_len > lcr_record2.prefix_len) {
michael@16 764 result = 1;
michael@16 765 } else if (lcr_record1.prefix_len == lcr_record2.prefix_len) {
michael@16 766 /* Sort by priority. */
michael@16 767 if (lcr_record1.priority < lcr_record2.priority) {
michael@16 768 result = 1;
michael@16 769 } else if (lcr_record1.priority == lcr_record2.priority) {
michael@16 770 /* Nothing to do. */
michael@16 771 result = 0;
michael@16 772 }
michael@16 773 }
michael@16 774 } else {
michael@16 775 if (lcr_record1.priority < lcr_record2.priority) {
michael@16 776 result = 1;
michael@16 777 } else if (lcr_record1.priority == lcr_record2.priority) {
michael@16 778 /* Nothing to do. */
michael@16 779 result = 0;
michael@16 780 }
michael@16 781 }
michael@16 782
michael@16 783 return result;
michael@16 784 }
michael@16 785
michael@16 786 /*
michael@16 787 * Sort lcr records by rand table.
michael@16 788 */
michael@16 789 static int rand_lcrs(const void *m1, const void *m2)
michael@16 790 {
michael@16 791 int result = -1;
michael@16 792
michael@16 793 struct mi mi1 = *((struct mi *) m1);
michael@16 794 struct mi mi2 = *((struct mi *) m2);
michael@16 795
michael@16 796 if (mi1.randomizer > mi2.randomizer) {
michael@16 797 result = 1;
michael@16 798 } else if (mi1.randomizer == mi2.randomizer) {
michael@16 799 result = 0;
michael@16 800 }
michael@16 801
michael@16 802 return result;
michael@16 803 }
michael@16 804
michael@16 805 /*
michael@16 806 * regcomp each prefix.
michael@16 807 */
michael@16 808 static int load_prefix_regex(void)
michael@16 809 {
michael@16 810 int i, status, result = 0;
michael@16 811
michael@16 812 for (i = 0; i < MAX_NO_OF_LCRS; i++) {
michael@16 813 if ((*lcrs)[i].end_record != 0) {
michael@16 814 break;
michael@16 815 }
michael@16 816 if (prefix_reg[i].valid) {
michael@16 817 regfree(&(prefix_reg[i].re));
michael@16 818 prefix_reg[i].valid = 0;
michael@16 819 }
michael@16 820 memset(&(prefix_reg[i].re), 0, sizeof(regex_t));
michael@16 821 if ((status=regcomp(&(prefix_reg[i].re),(*lcrs)[i].prefix,0))!=0){
michael@16 822 LM_ERR("bad prefix re <%s>, regcomp returned %d (check regex.h)\n",
michael@16 823 (*lcrs)[i].prefix, status);
michael@16 824 result = -1;
michael@16 825 break;
michael@16 826 }
michael@16 827 prefix_reg[i].valid = 1;
michael@16 828 }
michael@16 829
michael@16 830 return result;
michael@16 831 }
michael@16 832
michael@16 833 /*
michael@16 834 * regcomp each from_uri.
michael@16 835 */
michael@16 836 static int load_from_uri_regex(void)
michael@16 837 {
michael@16 838 int i, status, result = 0;
michael@16 839
michael@16 840 for (i = 0; i < MAX_NO_OF_LCRS; i++) {
michael@16 841 if ((*lcrs)[i].end_record != 0) {
michael@16 842 break;
michael@16 843 }
michael@16 844 if (from_uri_reg[i].valid) {
michael@16 845 regfree(&(from_uri_reg[i].re));
michael@16 846 from_uri_reg[i].valid = 0;
michael@16 847 }
michael@16 848 memset(&(from_uri_reg[i].re), 0, sizeof(regex_t));
michael@16 849 if ((status=regcomp(&(from_uri_reg[i].re),(*lcrs)[i].from_uri,0))!=0){
michael@16 850 LM_ERR("Bad from_uri re <%s>, regcomp returned %d (check regex.h)\n",
michael@16 851 (*lcrs)[i].from_uri, status);
michael@16 852 result = -1;
michael@16 853 break;
michael@16 854 }
michael@16 855 from_uri_reg[i].valid = 1;
michael@16 856 }
michael@16 857
michael@16 858 if (result != -1) {
michael@16 859 reload_counter = *lcrs_ws_reload_counter;
michael@16 860 }
michael@16 861 return result;
michael@16 862 }
michael@16 863
michael@16 864 static int load_all_regex(void)
michael@16 865 {
michael@16 866 int result =0;
michael@16 867
michael@16 868 if (prefix_mode_param != 0) {
michael@16 869 result = load_prefix_regex();
michael@16 870 }
michael@16 871
michael@16 872 if (result == 0) {
michael@16 873 result = load_from_uri_regex();
michael@16 874 } else {
michael@16 875 LM_ERR("Unable to load prefix regex\n");
michael@16 876 }
michael@16 877
michael@16 878 if (result == 0) {
michael@16 879 reload_counter = *lcrs_ws_reload_counter;
michael@16 880 } else {
michael@16 881 LM_ERR("Unable to load from_uri regex\n");
michael@16 882 }
michael@16 883
michael@16 884 return result;
michael@16 885 }
michael@16 886
michael@16 887 /*
michael@16 888 * Reload gws to unused gw table and lcrs to unused lcr table, and, when done
michael@16 889 * make unused gw and lcr table the one in use.
michael@16 890 */
michael@16 891 int reload_gws(void)
michael@16 892 {
michael@16 893 unsigned int i, port, strip, tag_len, prefix_len, from_uri_len,
michael@17 894 user_len, realm_len, passwd_len, grp_id, priority;
michael@16 895 struct in_addr ip_addr;
michael@16 896 unsigned int flags;
michael@16 897 uri_type scheme;
michael@16 898 uri_transport transport;
michael@16 899 db_con_t* dbh;
michael@16 900 char *tag, *prefix, *from_uri;
michael@17 901 char *user, *realm, *passwd;
michael@16 902 db_res_t* res = NULL;
michael@16 903 db_row_t* row;
michael@17 904 db_key_t gw_cols[11];
michael@16 905 db_key_t lcr_cols[4];
michael@16 906
michael@16 907 gw_cols[0] = &ip_addr_col;
michael@16 908 gw_cols[1] = &port_col;
michael@16 909 gw_cols[2] = &uri_scheme_col;
michael@16 910 gw_cols[3] = &transport_col;
michael@16 911 gw_cols[4] = &strip_col;
michael@16 912 gw_cols[5] = &tag_col;
michael@16 913 /* FIXME: is this ok if we have different names for grp_id
michael@16 914 in the two tables? (ge vw lcr) */
michael@16 915 gw_cols[6] = &grp_id_col;
michael@16 916 gw_cols[7] = &flags_col;
michael@17 917 gw_cols[8] = &user_col;
michael@17 918 gw_cols[9] = &realm_col;
michael@17 919 gw_cols[10] = &passwd_col;
michael@16 920
michael@16 921 lcr_cols[0] = &prefix_col;
michael@16 922 lcr_cols[1] = &from_uri_col;
michael@16 923 /* FIXME: is this ok if we have different names for grp_id
michael@16 924 in the two tables? (ge vw lcr) */
michael@16 925 lcr_cols[2] = &grp_id_col;
michael@16 926 lcr_cols[3] = &priority_col;
michael@16 927
michael@16 928 if (lcr_dbf.init==0){
michael@16 929 LM_CRIT("Unbound database\n");
michael@16 930 return -1;
michael@16 931 }
michael@16 932 dbh=lcr_dbf.init(&db_url);
michael@16 933 if (dbh==0){
michael@16 934 LM_ERR("Unable to open database connection\n");
michael@16 935 return -1;
michael@16 936 }
michael@16 937
michael@16 938 if (lcr_dbf.use_table(dbh, &gw_table) < 0) {
michael@16 939 LM_ERR("Error while trying to use gw table\n");
michael@16 940 return -1;
michael@16 941 }
michael@16 942
michael@17 943 if (lcr_dbf.query(dbh, NULL, 0, NULL, gw_cols, 0, 11, 0, &res) < 0) {
michael@16 944 LM_ERR("Failed to query gw data\n");
michael@16 945 lcr_dbf.close(dbh);
michael@16 946 return -1;
michael@16 947 }
michael@16 948
michael@16 949 if (RES_ROW_N(res) + 1 > MAX_NO_OF_GWS) {
michael@16 950 LM_ERR("Too many gateways\n");
michael@16 951 lcr_dbf.free_result(dbh, res);
michael@16 952 lcr_dbf.close(dbh);
michael@16 953 return -1;
michael@16 954 }
michael@16 955
michael@16 956 for (i = 0; i < RES_ROW_N(res); i++) {
michael@16 957 row = RES_ROWS(res) + i;
michael@16 958 if (!((VAL_TYPE(ROW_VALUES(row)) == DB_STRING) &&
michael@16 959 !VAL_NULL(ROW_VALUES(row)) &&
michael@16 960 inet_aton((char *)VAL_STRING(ROW_VALUES(row)), &ip_addr) != 0)) {
michael@16 961 LM_ERR("Invalid IP address of gw <%s>\n",
michael@16 962 (char *)VAL_STRING(ROW_VALUES(row)));
michael@16 963 lcr_dbf.free_result(dbh, res);
michael@16 964 lcr_dbf.close(dbh);
michael@16 965 return -1;
michael@16 966 }
michael@16 967 if (VAL_NULL(ROW_VALUES(row) + 1) == 1) {
michael@16 968 port = 0;
michael@16 969 } else {
michael@16 970 port = (unsigned int)VAL_INT(ROW_VALUES(row) + 1);
michael@16 971 }
michael@16 972 if (port > 65536) {
michael@16 973 LM_ERR("Port of gw is too large <%u>\n", port);
michael@16 974 lcr_dbf.free_result(dbh, res);
michael@16 975 lcr_dbf.close(dbh);
michael@16 976 return -1;
michael@16 977 }
michael@16 978 if (VAL_NULL(ROW_VALUES(row) + 2) == 1) {
michael@16 979 scheme = SIP_URI_T;
michael@16 980 } else {
michael@16 981 scheme = (uri_type)VAL_INT(ROW_VALUES(row) + 2);
michael@16 982 if ((scheme != SIP_URI_T) && (scheme != SIPS_URI_T)) {
michael@16 983 LM_ERR("Unknown or unsupported URI scheme <%u>\n",
michael@16 984 (unsigned int)scheme);
michael@16 985 lcr_dbf.free_result(dbh, res);
michael@16 986 lcr_dbf.close(dbh);
michael@16 987 return -1;
michael@16 988 }
michael@16 989 }
michael@16 990 if (VAL_NULL(ROW_VALUES(row) + 3) == 1) {
michael@16 991 transport = PROTO_NONE;
michael@16 992 } else {
michael@16 993 transport = (uri_transport)VAL_INT(ROW_VALUES(row) + 3);
michael@16 994 if ((transport != PROTO_UDP) && (transport != PROTO_TCP) &&
michael@16 995 (transport != PROTO_TLS)) {
michael@16 996 LM_ERR("Unknown or unsupported transport <%u>\n",
michael@16 997 (unsigned int)transport);
michael@16 998 lcr_dbf.free_result(dbh, res);
michael@16 999 lcr_dbf.close(dbh);
michael@16 1000 return -1;
michael@16 1001 }
michael@16 1002 }
michael@16 1003 if (VAL_NULL(ROW_VALUES(row) + 4) == 1) {
michael@16 1004 strip = 0;
michael@16 1005 } else {
michael@16 1006 strip = (unsigned int)VAL_INT(ROW_VALUES(row) + 4);
michael@16 1007 }
michael@16 1008 if (VAL_NULL(ROW_VALUES(row) + 5) == 1) {
michael@16 1009 tag_len = 0;
michael@16 1010 tag = (char *)0;
michael@16 1011 } else {
michael@16 1012 tag = (char *)VAL_STRING(ROW_VALUES(row) + 5);
michael@16 1013 tag_len = strlen(tag);
michael@16 1014 if (tag_len > MAX_TAG_LEN) {
michael@16 1015 LM_ERR("Too long gw tag <%u>\n", tag_len);
michael@16 1016 lcr_dbf.free_result(dbh, res);
michael@16 1017 lcr_dbf.close(dbh);
michael@16 1018 return -1;
michael@16 1019 }
michael@16 1020 }
michael@16 1021 if (VAL_NULL(ROW_VALUES(row) + 6) == 1) {
michael@16 1022 grp_id = 0;
michael@16 1023 } else {
michael@16 1024 grp_id = VAL_INT(ROW_VALUES(row) + 6);
michael@16 1025 }
michael@16 1026 if (!VAL_NULL(ROW_VALUES(row) + 7) &&
michael@16 1027 (VAL_TYPE(ROW_VALUES(row) + 7) == DB_INT)) {
michael@16 1028 flags = (unsigned int)VAL_INT(ROW_VALUES(row) + 7);
michael@16 1029 } else {
michael@16 1030 LM_ERR("Attribute flags is NULL or non-int\n");
michael@16 1031 lcr_dbf.free_result(dbh, res);
michael@16 1032 lcr_dbf.close(dbh);
michael@16 1033 return -1;
michael@16 1034 }
michael@17 1035 if (VAL_NULL(ROW_VALUES(row) + 8) == 1) {
michael@17 1036 user_len = 0;
michael@17 1037 user = (char *)0;
michael@17 1038 } else {
michael@17 1039 user = (char *)VAL_STRING(ROW_VALUES(row) + 8);
michael@17 1040 user_len = strlen(user);
michael@17 1041 if (user_len > MAX_USER_LEN) {
michael@17 1042 LM_ERR("Too long gw user <%u>\n", user_len);
michael@17 1043 lcr_dbf.free_result(dbh, res);
michael@17 1044 lcr_dbf.close(dbh);
michael@17 1045 return -1;
michael@17 1046 }
michael@17 1047 }
michael@17 1048 if (VAL_NULL(ROW_VALUES(row) + 9) == 1) {
michael@17 1049 realm_len = 0;
michael@17 1050 realm = (char *)0;
michael@17 1051 } else {
michael@17 1052 realm = (char *)VAL_STRING(ROW_VALUES(row) + 9);
michael@17 1053 realm_len = strlen(realm);
michael@17 1054 if (realm_len > MAX_REALM_LEN) {
michael@17 1055 LM_ERR("Too long gw realm <%u>\n", realm_len);
michael@17 1056 lcr_dbf.free_result(dbh, res);
michael@17 1057 lcr_dbf.close(dbh);
michael@17 1058 return -1;
michael@17 1059 }
michael@17 1060 }
michael@17 1061 if (VAL_NULL(ROW_VALUES(row) + 10) == 1) {
michael@17 1062 passwd_len = 0;
michael@17 1063 passwd = (char *)0;
michael@17 1064 } else {
michael@17 1065 passwd = (char *)VAL_STRING(ROW_VALUES(row) + 10);
michael@17 1066 passwd_len = strlen(passwd);
michael@17 1067 if (passwd_len > MAX_PASSWD_LEN) {
michael@17 1068 LM_ERR("Too long gw passwd <%u>\n", passwd_len);
michael@17 1069 lcr_dbf.free_result(dbh, res);
michael@17 1070 lcr_dbf.close(dbh);
michael@17 1071 return -1;
michael@17 1072 }
michael@17 1073 }
michael@16 1074 if (*gws == gws_1) {
michael@16 1075 gws_2[i].ip_addr = (unsigned int)ip_addr.s_addr;
michael@16 1076 gws_2[i].port = port;
michael@16 1077 gws_2[i].grp_id = grp_id;
michael@16 1078 gws_2[i].scheme = scheme;
michael@16 1079 gws_2[i].transport = transport;
michael@16 1080 gws_2[i].flags = flags;
michael@16 1081 gws_2[i].strip = strip;
michael@16 1082 gws_2[i].tag_len = tag_len;
michael@16 1083 if (tag_len)
michael@16 1084 memcpy(&(gws_2[i].tag[0]), tag, tag_len);
michael@17 1085 gws_2[i].user_len = user_len;
michael@17 1086 if (user_len)
michael@17 1087 memcpy(&(gws_2[i].user[0]), user, user_len);
michael@17 1088 gws_2[i].realm_len = realm_len;
michael@17 1089 if (realm_len)
michael@17 1090 memcpy(&(gws_2[i].realm[0]), realm, realm_len);
michael@17 1091 gws_2[i].passwd_len = passwd_len;
michael@17 1092 if (passwd_len)
michael@17 1093 memcpy(&(gws_2[i].passwd[0]), passwd, passwd_len);
michael@16 1094 } else {
michael@16 1095 gws_1[i].ip_addr = (unsigned int)ip_addr.s_addr;
michael@16 1096 gws_1[i].port = port;
michael@16 1097 gws_1[i].grp_id = grp_id;
michael@16 1098 gws_1[i].scheme = scheme;
michael@16 1099 gws_1[i].transport = transport;
michael@16 1100 gws_1[i].flags = flags;
michael@16 1101 gws_1[i].strip = strip;
michael@16 1102 gws_1[i].tag_len = tag_len;
michael@16 1103 if (tag_len)
michael@16 1104 memcpy(&(gws_1[i].tag[0]), tag, tag_len);
michael@17 1105 gws_1[i].user_len = user_len;
michael@17 1106 if (user_len)
michael@17 1107 memcpy(&(gws_1[i].user[0]), user, user_len);
michael@17 1108 gws_1[i].realm_len = realm_len;
michael@17 1109 if (realm_len)
michael@17 1110 memcpy(&(gws_1[i].realm[0]), realm, realm_len);
michael@17 1111 gws_1[i].passwd_len = passwd_len;
michael@17 1112 if (passwd_len)
michael@17 1113 memcpy(&(gws_1[i].passwd[0]), passwd, passwd_len);
michael@16 1114 }
michael@16 1115 }
michael@16 1116
michael@16 1117 lcr_dbf.free_result(dbh, res);
michael@16 1118
michael@16 1119 if (*gws == gws_1) {
michael@16 1120 gws_2[i].ip_addr = 0;
michael@16 1121 *gws = gws_2;
michael@16 1122 } else {
michael@16 1123 gws_1[i].ip_addr = 0;
michael@16 1124 *gws = gws_1;
michael@16 1125 }
michael@16 1126
michael@16 1127
michael@16 1128 if (lcr_dbf.use_table(dbh, &lcr_table) < 0) {
michael@16 1129 LM_ERR("Error while trying to use lcr table\n");
michael@16 1130 return -1;
michael@16 1131 }
michael@16 1132
michael@16 1133 if (lcr_dbf.query(dbh, NULL, 0, NULL, lcr_cols, 0, 4, 0, &res) < 0) {
michael@16 1134 LM_ERR("Failed to query lcr data\n");
michael@16 1135 lcr_dbf.close(dbh);
michael@16 1136 return -1;
michael@16 1137 }
michael@16 1138
michael@16 1139 if (RES_ROW_N(res) + 1 > MAX_NO_OF_LCRS) {
michael@16 1140 LM_ERR("Too many lcr entries <%d>\n", RES_ROW_N(res));
michael@16 1141 lcr_dbf.free_result(dbh, res);
michael@16 1142 lcr_dbf.close(dbh);
michael@16 1143 return -1;
michael@16 1144 }
michael@16 1145 for (i = 0; i < RES_ROW_N(res); i++) {
michael@16 1146 row = RES_ROWS(res) + i;
michael@16 1147 if (VAL_NULL(ROW_VALUES(row)) == 1) {
michael@16 1148 prefix_len = 0;
michael@16 1149 prefix = 0;
michael@16 1150 } else {
michael@16 1151 prefix = (char *)VAL_STRING(ROW_VALUES(row));
michael@16 1152 prefix_len = strlen(prefix);
michael@16 1153 if (prefix_len > MAX_PREFIX_LEN) {
michael@16 1154 LM_ERR("Too long lcr prefix <%u>\n", prefix_len);
michael@16 1155 lcr_dbf.free_result(dbh, res);
michael@16 1156 lcr_dbf.close(dbh);
michael@16 1157 return -1;
michael@16 1158 }
michael@16 1159 }
michael@16 1160 if (VAL_NULL(ROW_VALUES(row) + 1) == 1) {
michael@16 1161 from_uri_len = 0;
michael@16 1162 from_uri = 0;
michael@16 1163 } else {
michael@16 1164 from_uri = (char *)VAL_STRING(ROW_VALUES(row) + 1);
michael@16 1165 from_uri_len = strlen(from_uri);
michael@16 1166 if (from_uri_len > MAX_FROM_URI_LEN) {
michael@16 1167 LM_ERR("Too long from_uri <%u>\n", from_uri_len);
michael@16 1168 lcr_dbf.free_result(dbh, res);
michael@16 1169 lcr_dbf.close(dbh);
michael@16 1170 return -1;
michael@16 1171 }
michael@16 1172 }
michael@16 1173 if (VAL_NULL(ROW_VALUES(row) + 2) == 1) {
michael@16 1174 LM_ERR("Route grp_id is NULL\n");
michael@16 1175 lcr_dbf.free_result(dbh, res);
michael@16 1176 lcr_dbf.close(dbh);
michael@16 1177 return -1;
michael@16 1178 }
michael@16 1179 grp_id = (unsigned int)VAL_INT(ROW_VALUES(row) + 2);
michael@16 1180 if (VAL_NULL(ROW_VALUES(row) + 3) == 1) {
michael@16 1181 LM_ERR("Route priority is NULL\n");
michael@16 1182 lcr_dbf.free_result(dbh, res);
michael@16 1183 lcr_dbf.close(dbh);
michael@16 1184 return -1;
michael@16 1185 }
michael@16 1186 priority = (unsigned int)VAL_INT(ROW_VALUES(row) + 3);
michael@16 1187
michael@16 1188 if (*lcrs == lcrs_1) {
michael@16 1189 lcrs_2[i].prefix_len = prefix_len;
michael@16 1190 if (prefix_len)
michael@16 1191 memcpy(&(lcrs_2[i].prefix[0]), prefix, prefix_len);
michael@16 1192 lcrs_2[i].from_uri_len = from_uri_len;
michael@16 1193 if (from_uri_len) {
michael@16 1194 memcpy(&(lcrs_2[i].from_uri[0]), from_uri, from_uri_len);
michael@16 1195 lcrs_2[i].from_uri[from_uri_len] = '\0';
michael@16 1196 }
michael@16 1197 lcrs_2[i].grp_id = grp_id;
michael@16 1198 lcrs_2[i].priority = priority;
michael@16 1199 lcrs_2[i].end_record = 0;
michael@16 1200 } else {
michael@16 1201 lcrs_1[i].prefix_len = prefix_len;
michael@16 1202 if (prefix_len)
michael@16 1203 memcpy(&(lcrs_1[i].prefix[0]), prefix, prefix_len);
michael@16 1204 lcrs_1[i].from_uri_len = from_uri_len;
michael@16 1205 if (from_uri_len) {
michael@16 1206 memcpy(&(lcrs_1[i].from_uri[0]), from_uri, from_uri_len);
michael@16 1207 lcrs_1[i].from_uri[from_uri_len] = '\0';
michael@16 1208 }
michael@16 1209 lcrs_1[i].grp_id = grp_id;
michael@16 1210 lcrs_1[i].priority = priority;
michael@16 1211 lcrs_1[i].end_record = 0;
michael@16 1212 }
michael@16 1213 }
michael@16 1214
michael@16 1215 lcr_dbf.free_result(dbh, res);
michael@16 1216 lcr_dbf.close(dbh);
michael@16 1217
michael@16 1218 if (*lcrs == lcrs_1) {
michael@16 1219 lcrs_2[i].end_record = 1;
michael@16 1220 *lcrs = lcrs_2;
michael@16 1221 } else {
michael@16 1222 lcrs_1[i].end_record = 1;
michael@16 1223 *lcrs = lcrs_1;
michael@16 1224 }
michael@16 1225
michael@16 1226 (*lcrs_ws_reload_counter)++;
michael@16 1227 if (0 != load_all_regex()) {
michael@16 1228
michael@16 1229 return -1;
michael@16 1230 }
michael@16 1231
michael@16 1232 return 1;
michael@16 1233 }
michael@16 1234
michael@16 1235
michael@16 1236 int mi_print_gws(struct mi_node* rpl)
michael@16 1237 {
michael@16 1238 unsigned int i;
michael@16 1239 struct mi_attr* attr;
michael@16 1240 uri_transport transport;
michael@16 1241 char *transp;
michael@16 1242 struct mi_node* node;
michael@16 1243 struct ip_addr address;
michael@16 1244 char* p;
michael@16 1245 int len;
michael@16 1246
michael@16 1247 for (i = 0; i < MAX_NO_OF_GWS; i++) {
michael@16 1248
michael@16 1249 if ((*gws)[i].ip_addr == 0)
michael@16 1250 break;
michael@16 1251
michael@16 1252 node= add_mi_node_child(rpl,0 ,"GW", 2, 0, 0);
michael@16 1253 if(node == NULL)
michael@16 1254 return -1;
michael@16 1255
michael@16 1256 p = int2str((unsigned long)(*gws)[i].grp_id, &len );
michael@16 1257 attr = add_mi_attr(node, MI_DUP_VALUE, "GRP_ID", 6, p, len );
michael@16 1258 if(attr == NULL)
michael@16 1259 return -1;
michael@16 1260
michael@16 1261 transport = (*gws)[i].transport;
michael@16 1262 if (transport == PROTO_UDP)
michael@16 1263 transp= ";transport=udp";
michael@16 1264 else if (transport == PROTO_TCP)
michael@16 1265 transp= ";transport=tcp";
michael@16 1266 else if (transport == PROTO_TLS)
michael@16 1267 transp= ";transport=tls";
michael@16 1268 else
michael@16 1269 transp= "";
michael@16 1270
michael@16 1271 address.af = AF_INET;
michael@16 1272 address.len = 4;
michael@16 1273 address.u.addr32[0] = (*gws)[i].ip_addr;
michael@16 1274 attr= addf_mi_attr(node,0 ,"URI", 3,"%s:%s:%d%s",
michael@16 1275 ((*gws)[i].scheme == SIP_URI_T)?"sip":"sips",
michael@16 1276 ip_addr2a(&address),
michael@16 1277 ((*gws)[i].port == 0)?5060:(*gws)[i].port,transp);
michael@16 1278 if(attr == NULL)
michael@16 1279 return -1;
michael@16 1280
michael@16 1281 p = int2str((unsigned long)(*gws)[i].strip, &len );
michael@16 1282 attr = add_mi_attr(node, MI_DUP_VALUE, "STRIP", 5, p, len);
michael@16 1283 if(attr == NULL)
michael@16 1284 return -1;
michael@16 1285
michael@16 1286 attr = add_mi_attr(node, MI_DUP_VALUE, "TAG", 3,
michael@16 1287 (*gws)[i].tag, (*gws)[i].tag_len );
michael@16 1288 if(attr == NULL)
michael@16 1289 return -1;
michael@16 1290
michael@16 1291 p = int2str((unsigned long)(*gws)[i].flags, &len );
michael@16 1292 attr = add_mi_attr(node, MI_DUP_VALUE, "FLAGS", 5, p, len);
michael@16 1293 if(attr == NULL)
michael@16 1294 return -1;
michael@17 1295
michael@17 1296 attr = add_mi_attr(node, MI_DUP_VALUE, "USER", 6,
michael@17 1297 (*gws)[i].user, (*gws)[i].user_len );
michael@17 1298 if(attr == NULL)
michael@17 1299 return -1;
michael@17 1300
michael@17 1301 attr = add_mi_attr(node, MI_DUP_VALUE, "REALM", 6,
michael@17 1302 (*gws)[i].realm, (*gws)[i].realm_len );
michael@17 1303 if(attr == NULL)
michael@17 1304 return -1;
michael@17 1305
michael@17 1306 attr = add_mi_attr(node, MI_DUP_VALUE, "PASSWD", 6,
michael@17 1307 (*gws)[i].passwd, (*gws)[i].passwd_len );
michael@17 1308 if(attr == NULL)
michael@17 1309 return -1;
michael@16 1310 }
michael@16 1311
michael@16 1312 for (i = 0; i < MAX_NO_OF_LCRS; i++) {
michael@16 1313 if ((*lcrs)[i].end_record != 0)
michael@16 1314 break;
michael@16 1315
michael@16 1316 node= add_mi_node_child(rpl, 0, "RULE", 4, 0, 0);
michael@16 1317 attr = add_mi_attr(node, 0, "PREFIX", 6, (*lcrs)[i].prefix,
michael@16 1318 (*lcrs)[i].prefix_len );
michael@16 1319 if(attr== 0)
michael@16 1320 return -1;
michael@16 1321
michael@16 1322 attr = add_mi_attr(node, 0, "FROM_URI", 8, (*lcrs)[i].from_uri,
michael@16 1323 (*lcrs)[i].from_uri_len );
michael@16 1324 if(attr== 0)
michael@16 1325 return -1;
michael@16 1326
michael@16 1327 p = int2str((unsigned long)(*lcrs)[i].grp_id, &len );
michael@16 1328 attr = add_mi_attr(node, MI_DUP_VALUE, "GRP_ID", 6, p, len );
michael@16 1329 if(attr == NULL)
michael@16 1330 return -1;
michael@16 1331
michael@16 1332 p = int2str((unsigned long)(*lcrs)[i].priority, &len );
michael@16 1333 attr = add_mi_attr(node, MI_DUP_VALUE, "PRIORITY", 8, p, len );
michael@16 1334 if(attr == NULL)
michael@16 1335 return -1;
michael@16 1336
michael@16 1337 }
michael@16 1338
michael@16 1339 return 0;
michael@16 1340 }
michael@16 1341
michael@16 1342
michael@16 1343 /*
michael@16 1344 * Load info of matching GWs from database to gw_uri AVPs
michael@16 1345 */
michael@16 1346 static int do_load_gws(struct sip_msg* _m, str *_from_uri, int _grp_id)
michael@16 1347 {
michael@16 1348 str ruri_user, from_uri, value;
michael@16 1349 char from_uri_str[MAX_FROM_URI_LEN + 1];
michael@16 1350 char ruri[MAX_URI_SIZE];
michael@16 1351 unsigned int i, j, k, index, addr, port, strip, gw_index,
michael@16 1352 duplicated_gw, flags, have_rpid_avp;
michael@17 1353 char *user;
michael@17 1354 char *realm;
michael@17 1355 char *passwd;
michael@16 1356 uri_type scheme;
michael@16 1357 uri_transport transport;
michael@16 1358 struct ip_addr address;
michael@16 1359 str addr_str, port_str;
michael@16 1360 char *at, *tag, *strip_string, *flags_string;
michael@16 1361 struct usr_avp *avp;
michael@16 1362 int_str val;
michael@16 1363 struct mi matched_gws[MAX_NO_OF_GWS + 1];
michael@16 1364 unsigned short tag_len, prefix_len, priority;
michael@16 1365 int randomizer_start, randomizer_end, randomizer_flag,
michael@16 1366 strip_len, flags_len;
michael@16 1367 struct lcr_info lcr_rec;
michael@16 1368
michael@16 1369 /* Find Request-URI user */
michael@16 1370 if ((parse_sip_msg_uri(_m) < 0) || (!_m->parsed_uri.user.s)) {
michael@16 1371 LM_ERR("Error while parsing R-URI\n");
michael@16 1372 return -1;
michael@16 1373 }
michael@16 1374 ruri_user = _m->parsed_uri.user;
michael@16 1375
michael@16 1376 if (_from_uri) {
michael@16 1377 /* take caller uri from _from_uri argument */
michael@16 1378 from_uri = *_from_uri;
michael@16 1379 } else {
michael@16 1380 /* take caller uri from RPID or From URI */
michael@16 1381 have_rpid_avp = 0;
michael@16 1382 avp = search_first_avp(rpid_avp_type, rpid_avp, &val, 0);
michael@16 1383 if (avp != NULL) {
michael@16 1384 /* Get URI user from RPID if not empty */
michael@16 1385 if (avp->flags & AVP_VAL_STR) {
michael@16 1386 if (val.s.s && val.s.len) {
michael@16 1387 from_uri = val.s;
michael@16 1388 have_rpid_avp = 1;
michael@16 1389 }
michael@16 1390 } else {
michael@16 1391 from_uri.s = int2str(val.n, &from_uri.len);
michael@16 1392 have_rpid_avp = 1;
michael@16 1393 }
michael@16 1394 }
michael@16 1395 if (!have_rpid_avp) {
michael@16 1396 /* Get URI from From URI */
michael@16 1397 if ((!_m->from) && (parse_headers(_m, HDR_FROM_F, 0) == -1)) {
michael@16 1398 LM_ERR("Error while parsing headers\n");
michael@16 1399 return -1;
michael@16 1400 }
michael@16 1401 if (!_m->from) {
michael@16 1402 LM_ERR("From header field not found\n");
michael@16 1403 return -1;
michael@16 1404 }
michael@16 1405 if ((!(_m->from)->parsed) && (parse_from_header(_m) < 0)) {
michael@16 1406 LM_ERR("Error while parsing From header\n");
michael@16 1407 return -1;
michael@16 1408 }
michael@16 1409 from_uri = get_from(_m)->uri;
michael@16 1410 }
michael@16 1411 }
michael@16 1412 if (from_uri.len <= MAX_FROM_URI_LEN) {
michael@16 1413 strncpy(from_uri_str, from_uri.s, from_uri.len);
michael@16 1414 from_uri_str[from_uri.len] = '\0';
michael@16 1415 } else {
michael@16 1416 LM_ERR("From URI is too long <%u>\n", from_uri.len);
michael@16 1417 return -1;
michael@16 1418 }
michael@16 1419
michael@16 1420 /*
michael@16 1421 * Check if the gws and lcrs were reloaded
michael@16 1422 */
michael@16 1423 if (reload_counter != *lcrs_ws_reload_counter) {
michael@16 1424 if (load_all_regex() != 0) {
michael@16 1425 return -1;
michael@16 1426 }
michael@16 1427 }
michael@16 1428
michael@16 1429 /*
michael@16 1430 * Let's match the gws:
michael@16 1431 * 1. prefix matching
michael@16 1432 * 2. from_uri matching
michael@16 1433 * 3. _grp_id matching
michael@16 1434 *
michael@16 1435 * Note: A gateway must be in the list _only_ once.
michael@16 1436 */
michael@16 1437 gw_index = 0;
michael@16 1438 duplicated_gw = 0;
michael@16 1439 for (i = 0; i < MAX_NO_OF_LCRS; i++) {
michael@16 1440 lcr_rec = (*lcrs)[i];
michael@16 1441 if (lcr_rec.end_record != 0) {
michael@16 1442 break;
michael@16 1443 }
michael@16 1444 if ( ((prefix_mode_param == 0) && (lcr_rec.prefix_len <= ruri_user.len) &&
michael@16 1445 (strncmp(lcr_rec.prefix, ruri_user.s, lcr_rec.prefix_len)==0)) ||
michael@16 1446 ( (prefix_mode_param != 0) && ( (lcr_rec.prefix_len == 0) ||
michael@16 1447 (prefix_reg[i].valid &&
michael@16 1448 (regexec(&(prefix_reg[i].re), ruri_user.s, 0,
michael@16 1449 (regmatch_t *)NULL, 0) == 0)) ) ) ) {
michael@16 1450 /* 1. Prefix matching is done */
michael@16 1451 if ((lcr_rec.from_uri_len == 0) ||
michael@16 1452 (from_uri_reg[i].valid &&
michael@16 1453 (regexec(&(from_uri_reg[i].re), from_uri_str, 0,
michael@16 1454 (regmatch_t *)NULL, 0) == 0))) {
michael@16 1455 /* 2. from_uri matching is done */
michael@16 1456 for (j = 0; j < MAX_NO_OF_GWS; j++) {
michael@16 1457 if ((*gws)[j].ip_addr == 0) {
michael@16 1458 break;
michael@16 1459 }
michael@16 1460 if (lcr_rec.grp_id == (*gws)[j].grp_id &&
michael@16 1461 (_grp_id < 0 || (*gws)[j].grp_id == _grp_id)) {
michael@16 1462 /* 3. _grp_id matching is done */
michael@16 1463 for (k = 0; k < gw_index; k++) {
michael@16 1464 if ((*gws)[j].ip_addr ==
michael@16 1465 (*gws)[matched_gws[k].gw_index].ip_addr) {
michael@16 1466 /* Found the same gw in the list */
michael@16 1467 /* Let's keep the one with higher */
michael@16 1468 /* match on prefix len */
michael@16 1469 LM_DBG("Duplicate gw for index"
michael@16 1470 " %d [%d,%d] and current [%d,%d] \n",
michael@16 1471 k, matched_gws[k].route_index,
michael@16 1472 matched_gws[k].route_index, i, j);
michael@16 1473 duplicated_gw = 1;
michael@16 1474 if (lcr_rec.prefix_len >
michael@16 1475 (*lcrs)[matched_gws[k].route_index].prefix_len) {
michael@16 1476 /* Replace the old entry with the new one */
michael@16 1477 LM_DBG("Replace [%d,%d]"
michael@16 1478 " with [%d,%d] on index %d:"
michael@16 1479 " prefix reason %d>%d\n",
michael@16 1480 matched_gws[k].route_index,
michael@16 1481 matched_gws[k].gw_index, i, j, k,
michael@16 1482 lcr_rec.prefix_len,
michael@16 1483 (*lcrs)[matched_gws[k].route_index].prefix_len);
michael@16 1484 matched_gws[k].route_index = i;
michael@16 1485 matched_gws[k].gw_index = j;
michael@16 1486 /* Stop searching in the matched_gws list */
michael@16 1487 break;
michael@16 1488 } else if (lcr_rec.prefix_len ==
michael@16 1489 (*lcrs)[matched_gws[k].route_index].prefix_len) {
michael@16 1490 if (lcr_rec.priority >
michael@16 1491 (*lcrs)[matched_gws[k].route_index].priority) {
michael@16 1492 /* Replace the old entry with the new one */
michael@16 1493 LM_DBG("Replace [%d,%d] with"
michael@16 1494 " [%d,%d] on index %d:"
michael@16 1495 " priority reason %d>%d\n",
michael@16 1496 matched_gws[k].route_index,
michael@16 1497 matched_gws[k].gw_index,
michael@16 1498 i, j, k, lcr_rec.priority,
michael@16 1499 (*lcrs)[matched_gws[k].route_index].priority);
michael@16 1500 matched_gws[k].route_index = i;
michael@16 1501 matched_gws[k].gw_index = j;
michael@16 1502 /* Stop searching in the matched_gws list */
michael@16 1503 break;
michael@16 1504 }
michael@16 1505 }
michael@16 1506 }
michael@16 1507 }
michael@16 1508 if (duplicated_gw == 0) {
michael@16 1509 /* This is a new gw */
michael@16 1510 matched_gws[gw_index].route_index = i;
michael@16 1511 matched_gws[gw_index].gw_index = j;
michael@16 1512 LM_DBG("Added matched_gws[%d]=[%d,%d]\n",
michael@16 1513 gw_index, i, j);
michael@16 1514 gw_index++;
michael@16 1515 } else {
michael@16 1516 duplicated_gw = 0;
michael@16 1517 }
michael@16 1518 }
michael@16 1519 }
michael@16 1520 }
michael@16 1521 }
michael@16 1522 }
michael@16 1523 matched_gws[gw_index].route_index = -1;
michael@16 1524 matched_gws[gw_index].gw_index = -1;
michael@16 1525
michael@16 1526 /*
michael@16 1527 * Sort the gateways based on:
michael@16 1528 * 1. prefix len
michael@16 1529 * 2. priority
michael@16 1530 */
michael@16 1531 qsort(matched_gws, gw_index, sizeof(struct mi), comp_lcrs);
michael@16 1532 randomizer_start = 0;
michael@16 1533
michael@16 1534 /* Randomizing the gateways with same prefix_len and same priority */
michael@16 1535 randomizer_flag = 0;
michael@16 1536 prefix_len = (*lcrs)[matched_gws[0].route_index].prefix_len;
michael@16 1537 priority = (*lcrs)[matched_gws[0].route_index].priority;
michael@16 1538 for (i = 1; i < gw_index; i++) {
michael@16 1539 if ( prefix_len == (*lcrs)[matched_gws[i].route_index].prefix_len &&
michael@16 1540 priority == (*lcrs)[matched_gws[i].route_index].priority) {
michael@16 1541 /* we have a match */
michael@16 1542 if (randomizer_flag == 0) {
michael@16 1543 randomizer_flag = 1;
michael@16 1544 randomizer_start = i - 1;
michael@16 1545 }
michael@16 1546 matched_gws[i - 1].randomizer = rand();
michael@16 1547 }
michael@16 1548 else {
michael@16 1549 if (randomizer_flag == 1) {
michael@16 1550 randomizer_end = i - 1;
michael@16 1551 randomizer_flag = 0;
michael@16 1552 qsort(&matched_gws[randomizer_start],
michael@16 1553 randomizer_end - randomizer_start + 1,
michael@16 1554 sizeof(struct mi), rand_lcrs);
michael@16 1555 }
michael@16 1556 prefix_len = (*lcrs)[matched_gws[i].route_index].prefix_len;
michael@16 1557 priority = (*lcrs)[matched_gws[i].route_index].priority;
michael@16 1558 }
michael@16 1559 }
michael@16 1560 if (randomizer_flag == 1) {
michael@16 1561 randomizer_end = gw_index - 1;
michael@16 1562 matched_gws[i - 1].randomizer = rand();
michael@16 1563 qsort(&matched_gws[randomizer_start],
michael@16 1564 randomizer_end - randomizer_start + 1,
michael@16 1565 sizeof(struct mi), rand_lcrs);
michael@16 1566 }
michael@16 1567
michael@16 1568 for (i = 0; i < MAX_NO_OF_GWS; i++) {
michael@16 1569 index = matched_gws[i].gw_index;
michael@16 1570 if (index == -1) {
michael@16 1571 break;
michael@16 1572 }
michael@16 1573 addr = (*gws)[index].ip_addr;
michael@16 1574 port = (*gws)[index].port;
michael@16 1575 scheme = (*gws)[index].scheme;
michael@16 1576 transport = (*gws)[index].transport;
michael@16 1577 flags = (*gws)[index].flags;
michael@16 1578 strip = (*gws)[index].strip;
michael@17 1579 user = (*gws)[index].user;
michael@17 1580 realm = (*gws)[index].realm;
michael@17 1581 passwd = (*gws)[index].passwd;
michael@16 1582 if (strip > ruri_user.len) {
michael@16 1583 LM_ERR("Strip count of gw is too large <%u>\n", strip);
michael@16 1584 goto skip;
michael@16 1585 }
michael@16 1586 tag_len = (*gws)[index].tag_len;
michael@16 1587 tag = (*gws)[index].tag;
michael@16 1588 if (6 + tag_len + 40 /* flags + strip */ + 1 + 15 + 1 + 5 + 1 + 14 >
michael@16 1589 MAX_URI_SIZE) {
michael@16 1590 LM_ERR("Request URI would be too long\n");
michael@16 1591 goto skip;
michael@16 1592 }
michael@16 1593 at = (char *)&(ruri[0]);
michael@16 1594 flags_string = int2str(flags, &flags_len);
michael@16 1595 memcpy(at, flags_string, flags_len);
michael@16 1596 at = at + flags_len;
michael@16 1597 if (scheme == SIP_URI_T) {
michael@16 1598 memcpy(at, "sip:", 4); at = at + 4;
michael@16 1599 } else if (scheme == SIPS_URI_T) {
michael@16 1600 memcpy(at, "sips:", 5); at = at + 5;
michael@16 1601 } else {
michael@16 1602 LM_ERR("Unknown or unsupported URI scheme <%u>\n",
michael@16 1603 (unsigned int)scheme);
michael@16 1604 goto skip;
michael@16 1605 }
michael@16 1606 if (tag_len) {
michael@16 1607 memcpy(at, tag, tag_len); at = at + tag_len;
michael@16 1608 }
michael@16 1609 /* Add strip in this form |number.
michael@16 1610 * For example: |3 means strip first 3 characters.
michael@16 1611 */
michael@16 1612 *at = '|'; at = at + 1;
michael@16 1613 strip_string = int2str(strip, &strip_len);
michael@16 1614 memcpy(at, strip_string, strip_len);
michael@16 1615 at = at + strip_len;
michael@16 1616 *at = '@'; at = at + 1;
michael@16 1617 address.af = AF_INET;
michael@16 1618 address.len = 4;
michael@16 1619 address.u.addr32[0] = addr;
michael@16 1620 addr_str.s = ip_addr2a(&address);
michael@16 1621 addr_str.len = strlen(addr_str.s);
michael@16 1622 memcpy(at, addr_str.s, addr_str.len); at = at + addr_str.len;
michael@16 1623 if (port != 0) {
michael@16 1624 if (port > 65536) {
michael@16 1625 LM_ERR("Port of GW is too large <%u>\n", port);
michael@16 1626 goto skip;
michael@16 1627 }
michael@16 1628 *at = ':'; at = at + 1;
michael@16 1629 port_str.s = int2str(port, &port_str.len);
michael@16 1630 memcpy(at, port_str.s, port_str.len); at = at + port_str.len;
michael@16 1631 }
michael@16 1632 if (transport != PROTO_NONE) {
michael@16 1633 memcpy(at, ";transport=", 11); at = at + 11;
michael@16 1634 if (transport == PROTO_UDP) {
michael@16 1635 memcpy(at, "udp", 3); at = at + 3;
michael@16 1636 } else if (transport == PROTO_TCP) {
michael@16 1637 memcpy(at, "tcp", 3); at = at + 3;
michael@16 1638 } else if (transport == PROTO_TLS) {
michael@16 1639 memcpy(at, "tls", 3); at = at + 3;
michael@16 1640 } else {
michael@16 1641 LM_ERR("Unknown or unsupported transport <%u>\n",
michael@16 1642 (unsigned int)transport);
michael@16 1643 goto skip;
michael@16 1644 }
michael@16 1645 }
michael@16 1646 value.s = (char *)&(ruri[0]);
michael@16 1647 value.len = at - value.s;
michael@16 1648 val.s = value;
michael@16 1649 add_avp(gw_uri_avp_type|AVP_VAL_STR, gw_uri_avp, val);
michael@16 1650 LM_DBG("Added gw_uri_avp <%.*s>\n", value.len, value.s);
michael@17 1651
michael@17 1652 value.s = user;
michael@17 1653 value.len = strlen(value.s);
michael@17 1654 val.s = value;
michael@17 1655 add_avp(user_avp_type|AVP_VAL_STR, user_avp, val);
michael@17 1656 LM_DBG("Added user_avp <%.*s>\n", value.len, value.s);
michael@17 1657
michael@17 1658 value.s = realm;
michael@17 1659 value.len = strlen(value.s);
michael@17 1660 val.s = value;
michael@17 1661 add_avp(realm_avp_type|AVP_VAL_STR, realm_avp, val);
michael@17 1662 LM_DBG("Added realm_avp <%.*s>\n", value.len, value.s);
michael@17 1663
michael@17 1664 value.s = passwd;
michael@17 1665 value.len = strlen(value.s);
michael@17 1666 val.s = value;
michael@17 1667 add_avp(passwd_avp_type|AVP_VAL_STR, passwd_avp, val);
michael@17 1668 LM_DBG("Added passwd_avp <%.*s>\n", value.len, value.s);
michael@17 1669
michael@16 1670 skip:
michael@16 1671 continue;
michael@16 1672 }
michael@16 1673
michael@16 1674 return 1;
michael@16 1675 }
michael@16 1676
michael@16 1677 /*
michael@16 1678 * Load info of matching GWs from database to gw_uri AVPs
michael@16 1679 * taking into account the given group id. Caller URI is taken
michael@16 1680 * from request.
michael@16 1681 */
michael@16 1682 static int load_gws_from_grp(struct sip_msg* _m, char* _s1, char* _s2)
michael@16 1683 {
michael@16 1684 str grp_s;
michael@16 1685 unsigned int grp_id;
michael@16 1686
michael@16 1687 if(((pv_elem_p)_s1)->spec.getf!=NULL)
michael@16 1688 {
michael@16 1689 if(pv_printf_s(_m, (pv_elem_p)_s1, &grp_s)!=0)
michael@16 1690 return -1;
michael@16 1691 if(str2int(&grp_s, &grp_id)!=0)
michael@16 1692 return -1;
michael@16 1693 } else {
michael@16 1694 grp_id = ((pv_elem_p)_s1)->spec.pvp.pvn.u.isname.name.n;
michael@16 1695 }
michael@16 1696 if (grp_id > 0) return do_load_gws(_m, (str *)0, (int)grp_id);
michael@16 1697 else return -1;
michael@16 1698 }
michael@16 1699
michael@16 1700
michael@16 1701 /*
michael@16 1702 * Load info of matching GWs from database to gw_uri AVPs.
michael@16 1703 * Caller URI is taken from request.
michael@16 1704 */
michael@16 1705 static int load_gws_0(struct sip_msg* _m, char* _s1, char* _s2)
michael@16 1706 {
michael@16 1707 return do_load_gws(_m, (str *)0, -1);
michael@16 1708 }
michael@16 1709
michael@16 1710
michael@16 1711 /*
michael@16 1712 * Load info of matching GWs from database to gw_uri AVPs.
michael@16 1713 * Caller URI is taken from pseudo variable argument.
michael@16 1714 */
michael@16 1715 static int load_gws_1(struct sip_msg* _m, char* _sp, char* _s2)
michael@16 1716 {
michael@16 1717 pv_spec_t *sp;
michael@16 1718 pv_value_t pv_val;
michael@16 1719 sp = (pv_spec_t *)_sp;
michael@16 1720
michael@16 1721 if (sp && (pv_get_spec_value(_m, sp, &pv_val) == 0)) {
michael@16 1722 if (pv_val.flags & PV_VAL_STR) {
michael@16 1723 if (pv_val.rs.len == 0 || pv_val.rs.s == NULL) {
michael@16 1724 LM_DBG("missing from uri\n");
michael@16 1725 return -1;
michael@16 1726 }
michael@16 1727 return do_load_gws(_m, &(pv_val.rs), -1);
michael@16 1728 } else {
michael@16 1729 LM_DBG("pseudo variable value is not string\n");
michael@16 1730 return -1;
michael@16 1731 }
michael@16 1732 } else {
michael@16 1733 LM_DBG("cannot get pseudo variable value\n");
michael@16 1734 return -1;
michael@16 1735 }
michael@16 1736 }
michael@16 1737
michael@16 1738
michael@16 1739 /*
michael@16 1740 * Rewrites scheme, host, port, and transport parts of R-URI based on first
michael@16 1741 * gw_uri AVP value, which is then destroyed. Also saves R-URI user to
michael@16 1742 * ruri_user AVP for later use in failure route block.
michael@16 1743 * If called from failure route block, appends a new branch to request
michael@16 1744 * where scheme, host, port, and transport of URI are taken from the first
michael@16 1745 * gw_uri AVP value, which is then destroyed. URI user is taken from
michael@16 1746 * ruri_user AVP value saved earlier.
michael@16 1747 * Returns 1 upon success and -1 upon failure.
michael@16 1748 */
michael@16 1749 static int next_gw(struct sip_msg* _m, char* _s1, char* _s2)
michael@16 1750 {
michael@16 1751 int_str gw_uri_val, ruri_user_val, val;
michael@17 1752 int_str user_val, realm_val, passwd_val;
michael@17 1753 struct usr_avp *gu_avp, *ru_avp, *usr_avp, *rlm_avp, *pwd_avp;
michael@16 1754 int rval;
michael@16 1755 str new_ruri;
michael@16 1756 char *at, *at_char, *strip_char, *endptr;
michael@16 1757 unsigned int strip;
michael@16 1758
michael@16 1759 gu_avp = search_first_avp(gw_uri_avp_type, gw_uri_avp, &gw_uri_val, 0);
michael@16 1760 if (!gu_avp) return -1;
michael@16 1761
michael@16 1762 /* Set flags_avp from integer at the beginning of of gw_uri */
michael@16 1763 val.n = (int)strtoul(gw_uri_val.s.s, &at, 0);
michael@16 1764 add_avp(flags_avp_type, flags_avp, val);
michael@16 1765 LM_DBG("Added flags_avp <%u>\n", (unsigned int)val.n);
michael@16 1766
michael@16 1767 gw_uri_val.s.len = gw_uri_val.s.len - (at - gw_uri_val.s.s);
michael@16 1768 gw_uri_val.s.s = at;
michael@16 1769
michael@17 1770 /* Save gateway AVPs for use in script */
michael@17 1771 usr_avp = search_first_avp(user_avp_type, user_avp, &user_val, 0);
michael@17 1772 rlm_avp = search_first_avp(realm_avp_type, realm_avp, &realm_val, 0);
michael@17 1773 pwd_avp = search_first_avp(passwd_avp_type, passwd_avp, &passwd_val, 0);
michael@17 1774 if (!usr_avp) {
michael@17 1775 LM_DBG("User AVP no set\n");
michael@17 1776 return -1;
michael@17 1777 }
michael@17 1778 else {
michael@17 1779 add_avp(user_avp_type|AVP_VAL_STR, user_avp, user_val);
michael@17 1780 LM_DBG("Added user_avp <%.*s>\n", user_val.s.len, user_val.s.s);
michael@17 1781 }
michael@17 1782 if (!rlm_avp) {
michael@17 1783 LM_DBG("Realm AVP no set\n");
michael@17 1784 return -1;
michael@17 1785 }
michael@17 1786 else {
michael@17 1787 add_avp(realm_avp_type|AVP_VAL_STR, realm_avp, realm_val);
michael@17 1788 LM_DBG("Added realm_avp <%.*s>\n", realm_val.s.len, realm_val.s.s);
michael@17 1789 }
michael@17 1790 if (!pwd_avp) {
michael@17 1791 LM_DBG("Passwd AVP no set\n");
michael@17 1792 return -1;
michael@17 1793 }
michael@17 1794 else {
michael@17 1795 add_avp(passwd_avp_type|AVP_VAL_STR, passwd_avp, passwd_val);
michael@17 1796 LM_DBG("Added passwd_avp <%.*s>\n", passwd_val.s.len, passwd_val.s.s);
michael@17 1797 }
michael@17 1798
michael@16 1799 /* Create new Request-URI taking URI user from ruri_user AVP
michael@16 1800 and other parts of from gateway URI AVP. */
michael@16 1801 ru_avp = search_first_avp(ruri_user_avp_type, ruri_user_avp,
michael@16 1802 &ruri_user_val, 0);
michael@16 1803 if (!ru_avp) {
michael@16 1804 LM_DBG("ruri_user AVP no yet set -> use RURI\n");
michael@16 1805 /* parse RURI and ger username */
michael@16 1806 if (parse_sip_msg_uri(_m) < 0) {
michael@16 1807 LM_ERR("Parsing of R-URI failed\n");
michael@16 1808 return -1;
michael@16 1809 }
michael@16 1810 ruri_user_val.s = _m->parsed_uri.user;
michael@16 1811 /* Save Request-URI user for use in FAILURE_ROUTE */
michael@16 1812 val.s = _m->parsed_uri.user;
michael@16 1813 add_avp(ruri_user_avp_type|AVP_VAL_STR, ruri_user_avp, val);
michael@16 1814 LM_DBG("Added ruri_user_avp <%.*s>\n", val.s.len, val.s.s);
michael@16 1815 }
michael@16 1816
michael@16 1817 new_ruri.s = pkg_malloc(gw_uri_val.s.len + ruri_user_val.s.len);
michael@16 1818 if (!new_ruri.s) {
michael@16 1819 LM_ERR("No memory for new R-URI.\n");
michael@16 1820 return -1;
michael@16 1821 }
michael@16 1822 at_char = memchr(gw_uri_val.s.s, '@', gw_uri_val.s.len);
michael@16 1823 if (!at_char) {
michael@16 1824 pkg_free(new_ruri.s);
michael@16 1825 LM_ERR("No @ in gateway URI <%.*s>\n",
michael@16 1826 gw_uri_val.s.len, gw_uri_val.s.s);
michael@16 1827 return -1;
michael@16 1828 }
michael@16 1829 strip_char = memchr(gw_uri_val.s.s, '|', gw_uri_val.s.len);
michael@16 1830 if (!strip_char || strip_char + 1 >= at_char) {
michael@16 1831 pkg_free(new_ruri.s);
michael@16 1832 LM_ERR("No strip char | and at least one "
michael@16 1833 "char before @ in gateway URI <%.*s>\n",
michael@16 1834 gw_uri_val.s.len, gw_uri_val.s.s);
michael@16 1835 return -1;
michael@16 1836 }
michael@16 1837 at = new_ruri.s;
michael@16 1838 memcpy(at, gw_uri_val.s.s, strip_char - gw_uri_val.s.s);
michael@16 1839 at = at + (strip_char - gw_uri_val.s.s);
michael@16 1840 strip = strtol(strip_char + 1, &endptr, 10);
michael@16 1841 if (endptr != at_char) {
michael@16 1842 pkg_free(new_ruri.s);
michael@16 1843 LM_ERR("Non-digit char between | and @ chars in gw URI <%.*s>\n",
michael@16 1844 gw_uri_val.s.len, gw_uri_val.s.s);
michael@16 1845 return -1;
michael@16 1846 }
michael@16 1847 if (ruri_user_val.s.len - strip > 0) {
michael@16 1848 memcpy(at, ruri_user_val.s.s + strip,
michael@16 1849 ruri_user_val.s.len - strip);
michael@16 1850 at = at + ruri_user_val.s.len - strip;
michael@16 1851 }
michael@16 1852 if (*(at - 1) != ':') {
michael@16 1853 memcpy(at, at_char, gw_uri_val.s.len - (at_char - gw_uri_val.s.s));
michael@16 1854 at = at + gw_uri_val.s.len - (at_char - gw_uri_val.s.s);
michael@16 1855 } else {
michael@16 1856 memcpy(at, at_char + 1, gw_uri_val.s.len -
michael@16 1857 (at_char + 1 - gw_uri_val.s.s));
michael@16 1858 at = at + gw_uri_val.s.len - (at_char + 1 - gw_uri_val.s.s);
michael@16 1859 }
michael@16 1860 new_ruri.len = at - new_ruri.s;
michael@16 1861
michael@16 1862 /* set new RURI */
michael@16 1863 rval = set_ruri( _m, &new_ruri);
michael@16 1864 pkg_free(new_ruri.s);
michael@16 1865 destroy_avp(gu_avp);
michael@16 1866 if (rval!=0) {
michael@16 1867 LM_ERR("failed to set new RURI\n");
michael@16 1868 return -1;
michael@16 1869 }
michael@16 1870
michael@16 1871 return 1;
michael@16 1872 }
michael@16 1873
michael@16 1874
michael@16 1875 /*
michael@16 1876 * Checks if request comes from a gateway
michael@16 1877 */
michael@16 1878 static int do_from_gw(struct sip_msg* _m, pv_spec_t *addr_sp, int grp_id)
michael@16 1879 {
michael@16 1880 int i;
michael@16 1881 unsigned int src_addr;
michael@16 1882 pv_value_t pv_val;
michael@16 1883 struct ip_addr *ip;
michael@16 1884 int_str val;
michael@16 1885
michael@16 1886 if (addr_sp && (pv_get_spec_value(_m, addr_sp, &pv_val) == 0)) {
michael@16 1887 if (pv_val.flags & PV_VAL_INT) {
michael@16 1888 src_addr = pv_val.ri;
michael@16 1889 } else if (pv_val.flags & PV_VAL_STR) {
michael@16 1890 if ( (ip=str2ip( &pv_val.rs)) == NULL) {
michael@16 1891 LM_ERR("failed to convert IP address string to in_addr\n");
michael@16 1892 return -1;
michael@16 1893 } else {
michael@16 1894 src_addr = ip->u.addr32[0];
michael@16 1895 }
michael@16 1896 } else {
michael@16 1897 LM_ERR("IP address PV empty value\n");
michael@16 1898 return -1;
michael@16 1899 }
michael@16 1900 } else {
michael@16 1901 src_addr = _m->rcv.src_ip.u.addr32[0];
michael@16 1902 }
michael@16 1903
michael@16 1904 for (i = 0; i < MAX_NO_OF_GWS; i++) {
michael@16 1905 if ((*gws)[i].ip_addr == 0) {
michael@16 1906 return -1;
michael@16 1907 }
michael@16 1908 if ((*gws)[i].ip_addr == src_addr &&
michael@16 1909 (grp_id < 0 || (*gws)[i].grp_id == grp_id)) {
michael@16 1910 LM_DBG("Request came from gw\n");
michael@16 1911 val.n = (int)(*gws)[i].flags;
michael@16 1912 add_avp(flags_avp_type, flags_avp, val);
michael@16 1913 LM_DBG("Added flags_avp <%u>\n", (unsigned int)val.n);
michael@16 1914 return 1;
michael@16 1915 }
michael@16 1916 }
michael@16 1917
michael@16 1918 LM_DBG("Request did not come from gw\n");
michael@16 1919 return -1;
michael@16 1920 }
michael@16 1921
michael@16 1922
michael@16 1923 /*
michael@16 1924 * Checks if request comes from a gateway, taking source address from request
michael@16 1925 * and taking into account the group id.
michael@16 1926 */
michael@16 1927 static int from_gw_grp(struct sip_msg* _m, char* _grp_id, char* _s2)
michael@16 1928 {
michael@16 1929 return do_from_gw(_m, (pv_spec_t *)0, (int)(long)_grp_id);
michael@16 1930 }
michael@16 1931
michael@16 1932
michael@16 1933 /*
michael@16 1934 * Checks if request comes from a gateway, taking src_address from request
michael@16 1935 * and ignoring group id.
michael@16 1936 */
michael@16 1937 static int from_gw_0(struct sip_msg* _m, char* _s1, char* _s2)
michael@16 1938 {
michael@16 1939 return do_from_gw(_m, (pv_spec_t *)0, -1);
michael@16 1940 }
michael@16 1941
michael@16 1942
michael@16 1943 /*
michael@16 1944 * Checks if request comes from a gateway, taking source address from pw
michael@16 1945 * and ignoring group id.
michael@16 1946 */
michael@16 1947 static int from_gw_1(struct sip_msg* _m, char* _addr_sp, char* _s2)
michael@16 1948 {
michael@16 1949 return do_from_gw(_m, (pv_spec_t *)_addr_sp, -1);
michael@16 1950 }
michael@16 1951
michael@16 1952
michael@16 1953 /*
michael@16 1954 * Checks if in-dialog request goes to gateway
michael@16 1955 */
michael@16 1956 static int do_to_gw(struct sip_msg* _m, int grp_id)
michael@16 1957 {
michael@16 1958 char host[16];
michael@16 1959 struct in_addr addr;
michael@16 1960 unsigned int i;
michael@16 1961
michael@16 1962 if((_m->parsed_uri_ok == 0) && (parse_sip_msg_uri(_m) < 0)) {
michael@16 1963 LM_ERR("Error while parsing the R-URI\n");
michael@16 1964 return -1;
michael@16 1965 }
michael@16 1966
michael@16 1967 if (_m->parsed_uri.host.len > 15) {
michael@16 1968 return -1;
michael@16 1969 }
michael@16 1970 memcpy(host, _m->parsed_uri.host.s, _m->parsed_uri.host.len);
michael@16 1971 host[_m->parsed_uri.host.len] = 0;
michael@16 1972
michael@16 1973 if (!inet_aton(host, &addr)) {
michael@16 1974 return -1;
michael@16 1975 }
michael@16 1976
michael@16 1977 for (i = 0; i < MAX_NO_OF_GWS; i++) {
michael@16 1978 if ((*gws)[i].ip_addr == 0) {
michael@16 1979 return -1;
michael@16 1980 }
michael@16 1981 if ((*gws)[i].ip_addr == addr.s_addr &&
michael@16 1982 (grp_id < 0 || (*gws)[i].grp_id == grp_id)) {
michael@16 1983 return 1;
michael@16 1984 }
michael@16 1985 }
michael@16 1986
michael@16 1987 return -1;
michael@16 1988 }
michael@16 1989
michael@16 1990
michael@16 1991 /*
michael@16 1992 * Checks if in-dialog request goes to gateway, taking
michael@16 1993 * into account the group id.
michael@16 1994 */
michael@16 1995 static int to_gw_grp(struct sip_msg* _m, char* _s1, char* _s2)
michael@16 1996 {
michael@16 1997 int grp_id;
michael@16 1998
michael@16 1999 grp_id = (int)(long)_s1;
michael@16 2000 return do_to_gw(_m, grp_id);
michael@16 2001 }
michael@16 2002
michael@16 2003
michael@16 2004 /*
michael@16 2005 * Checks if in-dialog request goes to gateway, ignoring
michael@16 2006 * the group id.
michael@16 2007 */
michael@16 2008 static int to_gw(struct sip_msg* _m, char* _s1, char* _s2)
michael@16 2009 {
michael@16 2010 return do_to_gw(_m, -1);
michael@16 2011 }
michael@16 2012
michael@16 2013
michael@16 2014 /*
michael@16 2015 * Frees contact list used by load_contacts function
michael@16 2016 */
michael@16 2017 static inline void free_contact_list(struct contact *curr) {
michael@16 2018 struct contact *prev;
michael@16 2019 while (curr) {
michael@16 2020 prev = curr;
michael@16 2021 curr = curr->next;
michael@16 2022 pkg_free(prev);
michael@16 2023 }
michael@16 2024 }
michael@16 2025
michael@16 2026 /* Encode branch info from contact struct to str */
michael@16 2027 static inline int encode_branch_info(str *info, struct contact *con)
michael@16 2028 {
michael@16 2029 char *at, *s;
michael@16 2030 int len;
michael@16 2031
michael@16 2032 info->len = con->uri.len + con->dst_uri.len +
michael@16 2033 con->path.len + MAX_SOCKET_STR + INT2STR_MAX_LEN + 5;
michael@16 2034 info->s = pkg_malloc(info->len);
michael@16 2035 if (!info->s) {
michael@16 2036 LM_ERR("No memory left for branch info\n");
michael@16 2037 return 0;
michael@16 2038 }
michael@16 2039 at = info->s;
michael@16 2040 memcpy(at, con->uri.s, con->uri.len);
michael@16 2041 at = at + con->uri.len;
michael@16 2042 *at = '\n';
michael@16 2043 at++;
michael@16 2044 memcpy(at, con->dst_uri.s, con->dst_uri.len);
michael@16 2045 at = at + con->dst_uri.len;
michael@16 2046 *at = '\n';
michael@16 2047 at++;
michael@16 2048 memcpy(at, con->path.s, con->path.len);
michael@16 2049 at = at + con->path.len;
michael@16 2050 *at = '\n';
michael@16 2051 at++;
michael@16 2052 if (con->sock) {
michael@16 2053 len = MAX_SOCKET_STR;
michael@16 2054 if (!socket2str(con->sock, at, &len, 1)) {
michael@16 2055 LM_ERR("Failed to convert socket to str\n");
michael@16 2056 return 0;
michael@16 2057 }
michael@16 2058 } else {
michael@16 2059 len = 0;
michael@16 2060 }
michael@16 2061 at = at + len;
michael@16 2062 *at = '\n';
michael@16 2063 at++;
michael@16 2064 s = int2str(con->flags, &len);
michael@16 2065 memcpy(at, s, len);
michael@16 2066 at = at + len;
michael@16 2067 *at = '\n';
michael@16 2068 info->len = at - info->s + 1;
michael@16 2069
michael@16 2070 return 1;
michael@16 2071 }
michael@16 2072
michael@16 2073
michael@16 2074 /* Encode branch info from str */
michael@16 2075 static inline int decode_branch_info(char *info, str *uri, str *dst, str *path,
michael@16 2076 struct socket_info **sock, unsigned int *flags)
michael@16 2077 {
michael@16 2078 str s, host;
michael@16 2079 int port, proto;
michael@16 2080 char *pos, *at;
michael@16 2081
michael@16 2082 pos = strchr(info, '\n');
michael@16 2083 uri->len = pos - info;
michael@16 2084 if (uri->len) {
michael@16 2085 uri->s = info;
michael@16 2086 } else {
michael@16 2087 uri->s = 0;
michael@16 2088 }
michael@16 2089 at = pos + 1;
michael@16 2090
michael@16 2091 pos = strchr(at, '\n');
michael@16 2092 dst->len = pos - at;
michael@16 2093 if (dst->len) {
michael@16 2094 dst->s = at;
michael@16 2095 } else {
michael@16 2096 dst->s = 0;
michael@16 2097 }
michael@16 2098 at = pos + 1;
michael@16 2099
michael@16 2100 pos = strchr(at, '\n');
michael@16 2101 path->len = pos - at;
michael@16 2102 if (path->len) {
michael@16 2103 path->s = at;
michael@16 2104 } else {
michael@16 2105 path->s = 0;
michael@16 2106 }
michael@16 2107 at = pos + 1;
michael@16 2108
michael@16 2109 pos = strchr(at, '\n');
michael@16 2110 s.len = pos - at;
michael@16 2111 if (s.len) {
michael@16 2112 s.s = at;
michael@16 2113 if (parse_phostport(s.s, s.len, &host.s, &host.len,
michael@16 2114 &port, &proto) != 0) {
michael@16 2115 LM_ERR("Parsing of socket info <%.*s> failed\n", s.len, s.s);
michael@16 2116 return 0;
michael@16 2117 }
michael@16 2118 *sock = grep_sock_info(&host, (unsigned short)port,
michael@16 2119 (unsigned short)proto);
michael@16 2120 if (*sock == 0) {
michael@16 2121 LM_ERR("Invalid socket <%.*s>\n", s.len, s.s);
michael@16 2122 return 0;
michael@16 2123 }
michael@16 2124 } else {
michael@16 2125 *sock = 0;
michael@16 2126 }
michael@16 2127 at = pos + 1;
michael@16 2128
michael@16 2129 pos = strchr(at, '\n');
michael@16 2130 s.len = pos - at;
michael@16 2131 if (s.len) {
michael@16 2132 s.s = at;
michael@16 2133 if (str2int(&s, flags) != 0) {
michael@16 2134 LM_ERR("Failed to decode flags <%.*s>\n", s.len, s.s);
michael@16 2135 return 0;
michael@16 2136 }
michael@16 2137 } else {
michael@16 2138 *flags = 0;
michael@16 2139 }
michael@16 2140
michael@16 2141 return 1;
michael@16 2142 }
michael@16 2143
michael@16 2144
michael@16 2145 /*
michael@16 2146 * Loads contacts in destination set into "lcr_contact" AVP in reverse
michael@16 2147 * priority order and associated each contact with Q_FLAG telling if
michael@16 2148 * contact is the last one in its priority class. Finally, removes
michael@16 2149 * all branches from destination set.
michael@16 2150 */
michael@16 2151 static int load_contacts(struct sip_msg* msg, char* key, char* value)
michael@16 2152 {
michael@16 2153 str uri, dst_uri, path, branch_info, *ruri;
michael@16 2154 qvalue_t q, ruri_q;
michael@16 2155 struct contact *contacts, *next, *prev, *curr;
michael@16 2156 int_str val;
michael@16 2157 int idx;
michael@16 2158 struct socket_info* sock;
michael@16 2159 unsigned int flags;
michael@16 2160
michael@16 2161 /* Check if anything needs to be done */
michael@16 2162 if (nr_branches == 0) {
michael@16 2163 LM_DBG("Nothing to do - no branches!\n");
michael@16 2164 return 1;
michael@16 2165 }
michael@16 2166
michael@16 2167 ruri = GET_RURI(msg);
michael@16 2168 if (!ruri) {
michael@16 2169 LM_ERR("No Request-URI found\n");
michael@16 2170 return -1;
michael@16 2171 }
michael@16 2172 ruri_q = get_ruri_q();
michael@16 2173
michael@16 2174 for(idx = 0; (uri.s = get_branch(idx, &uri.len, &q, 0, 0, 0, 0)) != 0;
michael@16 2175 idx++) {
michael@16 2176 if (q != ruri_q) {
michael@16 2177 goto rest;
michael@16 2178 }
michael@16 2179 }
michael@16 2180 LM_DBG("Nothing to do - all contacts have same q!\n");
michael@16 2181 return 1;
michael@16 2182
michael@16 2183 rest:
michael@16 2184 /* Insert Request-URI branch to contact list */
michael@16 2185 contacts = (struct contact *)pkg_malloc(sizeof(struct contact));
michael@16 2186 if (!contacts) {
michael@16 2187 LM_ERR("No memory for contact info\n");
michael@16 2188 return -1;
michael@16 2189 }
michael@16 2190 contacts->uri.s = ruri->s;
michael@16 2191 contacts->uri.len = ruri->len;
michael@16 2192 contacts->q = ruri_q;
michael@16 2193 contacts->dst_uri = msg->dst_uri;
michael@16 2194 contacts->sock = msg->force_send_socket;
michael@16 2195 contacts->flags = getb0flags();
michael@16 2196 contacts->path = msg->path_vec;
michael@16 2197 contacts->next = (struct contact *)0;
michael@16 2198
michael@16 2199 /* Insert branches to contact list in increasing q order */
michael@16 2200 for(idx = 0;
michael@16 2201 (uri.s = get_branch(idx,&uri.len,&q,&dst_uri,&path,&flags,&sock))
michael@16 2202 != 0;
michael@16 2203 idx++ ) {
michael@16 2204 next = (struct contact *)pkg_malloc(sizeof(struct contact));
michael@16 2205 if (!next) {
michael@16 2206 LM_ERR("No memory for contact info\n");
michael@16 2207 free_contact_list(contacts);
michael@16 2208 return -1;
michael@16 2209 }
michael@16 2210 next->uri = uri;
michael@16 2211 next->q = q;
michael@16 2212 next->dst_uri = dst_uri;
michael@16 2213 next->path = path;
michael@16 2214 next->flags = flags;
michael@16 2215 next->sock = sock;
michael@16 2216 next->next = (struct contact *)0;
michael@16 2217 prev = (struct contact *)0;
michael@16 2218 curr = contacts;
michael@16 2219 while (curr && (curr->q < q)) {
michael@16 2220 prev = curr;
michael@16 2221 curr = curr->next;
michael@16 2222 }
michael@16 2223 if (!curr) {
michael@16 2224 next->next = (struct contact *)0;
michael@16 2225 prev->next = next;
michael@16 2226 } else {
michael@16 2227 next->next = curr;
michael@16 2228 if (prev) {
michael@16 2229 prev->next = next;
michael@16 2230 } else {
michael@16 2231 contacts = next;
michael@16 2232 }
michael@16 2233 }
michael@16 2234 }
michael@16 2235
michael@16 2236 /* Assign values for q_flags */
michael@16 2237 curr = contacts;
michael@16 2238 curr->q_flag = 0;
michael@16 2239 while (curr->next) {
michael@16 2240 if (curr->q < curr->next->q) {
michael@16 2241 curr->next->q_flag = Q_FLAG;
michael@16 2242 } else {
michael@16 2243 curr->next->q_flag = 0;
michael@16 2244 }
michael@16 2245 curr = curr->next;
michael@16 2246 }
michael@16 2247
michael@16 2248 /* Add contacts to "contacts" AVP */
michael@16 2249 curr = contacts;
michael@16 2250 while (curr) {
michael@16 2251 if (encode_branch_info(&branch_info, curr) == 0) {
michael@16 2252 LM_ERR("Encoding of branch info failed\n");
michael@16 2253 free_contact_list(contacts);
michael@16 2254 if (branch_info.s) pkg_free(branch_info.s);
michael@16 2255 return -1;
michael@16 2256 }
michael@16 2257 val.s = branch_info;
michael@16 2258 add_avp(contact_avp_type|AVP_VAL_STR|(curr->q_flag),
michael@16 2259 contact_avp, val);
michael@16 2260 pkg_free(branch_info.s);
michael@16 2261 LM_DBG("Loaded contact <%.*s> with q_flag <%d>\n",
michael@16 2262 val.s.len, val.s.s, curr->q_flag);
michael@16 2263 curr = curr->next;
michael@16 2264 }
michael@16 2265
michael@16 2266 /* Clear all branches */
michael@16 2267 clear_branches();
michael@16 2268
michael@16 2269 /* Free contact list */
michael@16 2270 free_contact_list(contacts);
michael@16 2271
michael@16 2272 return 1;
michael@16 2273 }
michael@16 2274
michael@16 2275
michael@16 2276 /*
michael@16 2277 * Adds to request a destination set that includes all highest priority
michael@16 2278 * class contacts in "lcr_contact" AVP. If called from a route block,
michael@16 2279 * rewrites the request uri with first contact and adds the remaining
michael@16 2280 * contacts as branches. If called from failure route block, adds all
michael@16 2281 * contacts as branches. Removes added contacts from "lcr_contact" AVP.
michael@16 2282 */
michael@16 2283 static int next_contacts(struct sip_msg* msg, char* key, char* value)
michael@16 2284 {
michael@16 2285 struct usr_avp *avp, *prev;
michael@16 2286 int_str val;
michael@16 2287 str uri, dst, path;
michael@16 2288 struct socket_info *sock;
michael@16 2289 unsigned int flags;
michael@16 2290
michael@16 2291 /* Find first lcr_contact_avp value */
michael@16 2292 avp = search_first_avp(contact_avp_type, contact_avp, &val, 0);
michael@16 2293 if (!avp) {
michael@16 2294 LM_DBG("No AVPs -- we are done!\n");
michael@16 2295 return -1;
michael@16 2296 }
michael@16 2297
michael@16 2298 LM_DBG("Next contact is <%s>\n", val.s.s);
michael@16 2299
michael@16 2300 if (decode_branch_info(val.s.s, &uri, &dst, &path, &sock, &flags)== 0) {
michael@16 2301 LM_ERR("Decoding of branch info <%.*s> failed\n",
michael@16 2302 val.s.len, val.s.s);
michael@16 2303 destroy_avp(avp);
michael@16 2304 return -1;
michael@16 2305 }
michael@16 2306
michael@16 2307 set_ruri(msg, &uri);
michael@16 2308 set_dst_uri(msg, &dst);
michael@16 2309 set_path_vector(msg, &path);
michael@16 2310 msg->force_send_socket = sock;
michael@16 2311 setb0flags(flags);
michael@16 2312
michael@16 2313 if (avp->flags & Q_FLAG) {
michael@16 2314 destroy_avp(avp);
michael@16 2315 if (route_type == REQUEST_ROUTE) {
michael@16 2316 /* Set fr_inv_timer */
michael@16 2317 val.n = fr_inv_timer_next;
michael@16 2318 if (add_avp(fr_inv_timer_avp_type, fr_inv_timer_avp, val) != 0) {
michael@16 2319 LM_ERR("Setting of fr_inv_timer_avp failed\n");
michael@16 2320 return -1;
michael@16 2321 }
michael@16 2322 }
michael@16 2323 return 1;
michael@16 2324 }
michael@16 2325
michael@16 2326 /* Append branches until out of branches or Q_FLAG is set */
michael@16 2327 prev = avp;
michael@16 2328 while ((avp = search_next_avp(avp, &val))) {
michael@16 2329 destroy_avp(prev);
michael@16 2330
michael@16 2331 LM_DBG("Next contact is <%s>\n", val.s.s);
michael@16 2332
michael@16 2333 if (decode_branch_info(val.s.s, &uri, &dst, &path, &sock, &flags)== 0){
michael@16 2334 LM_ERR("Decoding of branch info <%.*s> failed\n",
michael@16 2335 val.s.len, val.s.s);
michael@16 2336 destroy_avp(avp);
michael@16 2337 return -1;
michael@16 2338 }
michael@16 2339
michael@16 2340 if (append_branch(msg, &uri, &dst, &path, 0, flags, sock) != 1) {
michael@16 2341 LM_ERR("Appending branch failed\n");
michael@16 2342 destroy_avp(avp);
michael@16 2343 return -1;
michael@16 2344 }
michael@16 2345
michael@16 2346 if (avp->flags & Q_FLAG) {
michael@16 2347 destroy_avp(avp);
michael@16 2348 if (route_type == REQUEST_ROUTE) {
michael@16 2349 val.n = fr_inv_timer_next;
michael@16 2350 if (add_avp(fr_inv_timer_avp_type, fr_inv_timer_avp, val)!= 0){
michael@16 2351 LM_ERR("Setting of fr_inv_timer_avp failed\n");
michael@16 2352 return -1;
michael@16 2353 }
michael@16 2354 }
michael@16 2355 return 1;
michael@16 2356 }
michael@16 2357 prev = avp;
michael@16 2358 }
michael@16 2359
michael@16 2360 /* Restore fr_inv_timer */
michael@16 2361 val.n = fr_inv_timer;
michael@16 2362 if (add_avp(fr_inv_timer_avp_type, fr_inv_timer_avp, val) != 0) {
michael@16 2363 LM_ERR("Setting of fr_inv_timer_avp failed\n");
michael@16 2364 return -1;
michael@16 2365 }
michael@16 2366
michael@16 2367 return 1;
michael@16 2368 }
michael@16 2369
michael@16 2370
michael@16 2371 /*
michael@16 2372 * Convert string parameter to integer for functions that expect an integer.
michael@16 2373 * Taken from sl module.
michael@16 2374 */
michael@16 2375 static int fixstringloadgws(void **param, int param_count)
michael@16 2376 {
michael@16 2377 pv_elem_t *model=NULL;
michael@16 2378 str s;
michael@16 2379
michael@16 2380 /* convert to str */
michael@16 2381 s.s = (char*)*param;
michael@16 2382 s.len = strlen(s.s);
michael@16 2383
michael@16 2384 model=NULL;
michael@16 2385 if (param_count==1) {
michael@16 2386 if(s.len==0) {
michael@16 2387 LM_ERR("No param <%d>!\n", param_count);
michael@16 2388 return -1;
michael@16 2389 }
michael@16 2390
michael@16 2391 if(pv_parse_format(&s,&model)<0 || model==NULL) {
michael@16 2392 LM_ERR("Wrong format <%s> for param <%d>!\n", s.s, param_count);
michael@16 2393 return -1;
michael@16 2394 }
michael@16 2395 if(model->spec.getf==NULL) {
michael@16 2396 if(param_count==1) {
michael@16 2397 if(str2int(&s, (unsigned int*)&model->spec.pvp.pvn.u.isname.name.n)!=0) {
michael@16 2398 LM_ERR("Wrong value <%s> for param <%d>!\n",
michael@16 2399 s.s, param_count);
michael@16 2400 return -1;
michael@16 2401 }
michael@16 2402 }
michael@16 2403 }
michael@16 2404 *param = (void*)model;
michael@16 2405 }
michael@16 2406
michael@16 2407 return 0;
michael@16 2408 }

mercurial