123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400 |
- /*
- * $Id$
- *
- * Copyright (C) 2004 FhG Fokus
- *
- * This file is part of ser, a free SIP server.
- *
- * ser is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version
- *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- * [email protected]
- *
- * ser is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
- /*
- * History:
- * --------
- * 2004-06-14 added ability to read default values from DB table usr_preferences_types (kozlik)
- */
- #include <string.h>
- #include "../../sr_module.h"
- #include "../../mem/mem.h"
- #include "../../parser/msg_parser.h"
- #include "../../parser/hf.h"
- #include "../../parser/parse_from.h"
- #include "../../parser/parse_to.h"
- #include "../../parser/parse_uri.h"
- #include "../../str.h"
- #include "../../lib/srdb2/db.h"
- #include "../../config.h"
- #include "../../usr_avp.h"
- #include "../../ut.h"
- #include "../../id.h"
- #include "../uid_domain/domain.h"
- #include "uid_avp_db.h"
- #include "extra_attrs.h"
- MODULE_VERSION
- static char* db_url = DEFAULT_RODB_URL; /* Database URL */
- static char* user_attrs_table = "uid_user_attrs";
- static char* uri_attrs_table = "uid_uri_attrs";
- static char* uid_column = "uid";
- static char* username_column = "username";
- static char* did_column = "did";
- static char* name_column = "name";
- static char* type_column = "type";
- static char* val_column = "value";
- static char* flags_column = "flags";
- static char* scheme_column = "scheme";
- int auto_unlock = 0;
- db_ctx_t* ctx = 0;
- db_cmd_t *load_user_attrs_cmd = NULL;
- db_cmd_t *load_uri_attrs_cmd = NULL;
- static int mod_init(void);
- static int child_init(int);
- static int load_attrs(struct sip_msg* msg, char* s1, char* s2);
- static int attrs_fixup(void** param, int param_no);
- static domain_get_did_t dm_get_did = NULL;
- /*
- * Exported functions
- */
- static cmd_export_t cmds[] = {
- {"load_attrs", load_attrs, 2, attrs_fixup, REQUEST_ROUTE | FAILURE_ROUTE},
-
- /* functions for loading/storing flagged attributes into DB */
- {"load_extra_attrs", load_extra_attrs, 2, extra_attrs_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE},
- {"save_extra_attrs", save_extra_attrs, 2, extra_attrs_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE},
- {"remove_extra_attrs", remove_extra_attrs, 2, extra_attrs_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE},
- /* locking attrs - needed for proper work! */
- {"lock_extra_attrs", lock_extra_attrs, 2, extra_attrs_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE},
- {"unlock_extra_attrs", unlock_extra_attrs, 2, extra_attrs_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE},
-
- {0, 0, 0, 0, 0}
- };
- /*
- * Exported parameters
- */
- static param_export_t params[] = {
- {"db_url", PARAM_STRING, &db_url },
- {"user_attrs_table", PARAM_STRING, &user_attrs_table},
- {"uri_attrs_table", PARAM_STRING, &uri_attrs_table },
- {"uid_column", PARAM_STRING, &uid_column },
- {"username_column", PARAM_STRING, &username_column },
- {"did_column", PARAM_STRING, &did_column },
- {"name_column", PARAM_STRING, &name_column },
- {"type_column", PARAM_STRING, &type_column },
- {"value_column", PARAM_STRING, &val_column },
- {"flags_column", PARAM_STRING, &flags_column },
- {"scheme_column", PARAM_STRING, &scheme_column },
- {"attr_group", PARAM_STR | PARAM_USE_FUNC, (void*)declare_attr_group },
- {"auto_unlock_extra_attrs", PARAM_INT, &auto_unlock },
- {0, 0, 0}
- };
- struct module_exports exports = {
- "uid_avp_db",
- cmds, /* Exported commands */
- 0, /* RPC methods */
- params, /* Exported parameters */
- mod_init, /* module initialization function */
- 0, /* response function*/
- 0, /* destroy function */
- 0, /* oncancel function */
- child_init /* per-child init function */
- };
- static int mod_init(void)
- {
- return init_extra_avp_locks();
- }
- static int child_init(int rank)
- {
- db_fld_t res_cols[] = {
- {.name = name_column, .type = DB_STR},
- {.name = type_column, .type = DB_INT},
- {.name = val_column, .type = DB_STR},
- {.name = flags_column, .type = DB_BITMAP},
- {.name = NULL}
- };
- db_fld_t match_uri[] = {
- {.name = username_column, .type = DB_STR, .op = DB_EQ},
- {.name = did_column, .type = DB_STR, .op = DB_EQ},
- {.name = scheme_column, .type = DB_STR, .op = DB_EQ},
- {.name = NULL}
- };
- db_fld_t match_user[] = {
- {.name = uid_column, .type = DB_STR, .op = DB_EQ},
- {.name = NULL}
- };
- if (rank==PROC_INIT || rank==PROC_MAIN || rank==PROC_TCP_MAIN)
- return 0; /* do nothing for the main process */
-
- ctx = db_ctx("avp_db");
- if (!ctx) goto err;
- if (db_add_db(ctx, db_url) < 0) goto err;
- if (db_connect(ctx) < 0) goto err;
-
- load_uri_attrs_cmd = db_cmd(DB_GET, ctx, uri_attrs_table, res_cols, match_uri, NULL);
- if (!load_uri_attrs_cmd) goto err;
- load_user_attrs_cmd = db_cmd(DB_GET, ctx, user_attrs_table, res_cols, match_user, NULL);
- if (!load_user_attrs_cmd) goto err;
- if (init_extra_avp_queries(ctx) < 0) goto err;
- return 0;
- err:
- if (load_uri_attrs_cmd) db_cmd_free(load_uri_attrs_cmd);
- if (load_user_attrs_cmd) db_cmd_free(load_user_attrs_cmd);
- if (ctx) db_ctx_free(ctx);
- ERR("Error while initializing database layer\n");
- return -1;
- }
- #define IS_DB_NULL(f) (f.flags & DB_NULL)
- static void read_attrs(db_res_t *res, unsigned long flags)
- {
- int_str name, v;
- str avp_val;
- int type, n, found;
- db_rec_t* row;
- n = 0;
- found = 0;
- /* AVP names from DB are always strings */
- flags |= AVP_NAME_STR;
- if (res) row = db_first(res);
- else row = NULL;
- while (row) {
- found++;
- if (IS_DB_NULL(row->fld[0]) ||
- IS_DB_NULL(row->fld[1]) ||
- IS_DB_NULL(row->fld[3])) {
- ERR("Skipping row containing NULL entries\n");
- row = db_next(res);
- continue;
- }
- if ((row->fld[3].v.int4 & SRDB_LOAD_SER) == 0) {
- row = db_next(res);
- continue;
- }
- n++;
- /* Get AVP name */
- name.s = row->fld[0].v.lstr;
- /* Get AVP type */
- type = row->fld[1].v.int4;
- /* Test for NULL value */
- if (IS_DB_NULL(row->fld[2])) {
- avp_val.s = 0;
- avp_val.len = 0;
- } else {
- avp_val = row->fld[2].v.lstr;
- }
- if (type == AVP_VAL_STR) {
- /* String AVP */
- v.s = avp_val;
- flags |= AVP_VAL_STR;
- } else {
- /* Integer AVP */
- str2int(&avp_val, (unsigned*)&v.n);
- /* reset val_str as the value could be an integer */
- flags &= ~AVP_VAL_STR;
- }
- if (add_avp(flags, name, v) < 0) {
- ERR("Error while adding user attribute %.*s, skipping\n",
- name.s.len, ZSW(name.s.s));
- }
- row = db_next(res);
- }
- DBG("avp_db:load_attrs: %d attributes found, %d loaded\n", found, n);
- }
- static int load_uri_attrs(struct sip_msg* msg, unsigned long flags, fparam_t* fp)
- {
- db_res_t* res;
- str uri;
- struct sip_uri puri;
- static str default_did = STR_STATIC_INIT(DEFAULT_DID);
- if (get_str_fparam(&uri, msg, (fparam_t*)fp) != 0) {
- DBG("Unable to get URI from load_uri_attrs parameters\n");
- return -1;
- }
- if (parse_uri(uri.s, uri.len, &puri) < 0) {
- ERR("Error while parsing URI '%.*s'\n", uri.len, uri.s);
- return -1;
- }
- load_uri_attrs_cmd->match[0].v.lstr = puri.user;
- if (puri.host.len) {
- /* domain name is present */
- if (dm_get_did(&load_uri_attrs_cmd->match[1].v.lstr, &puri.host) < 0) {
- DBG("Cannot lookup DID for domain %.*s, using default value\n", puri.host.len, ZSW(puri.host.s));
- load_uri_attrs_cmd->match[1].v.lstr = default_did;
- }
- } else {
- /* domain name is missing -- can be caused by tel: URI */
- DBG("There is no domain name, using default value\n");
- load_uri_attrs_cmd->match[1].v.lstr = default_did;
- }
- uri_type_to_str(puri.type, &(load_uri_attrs_cmd->match[2].v.lstr));
- if (db_exec(&res, load_uri_attrs_cmd) < 0) {
- ERR("Error while querying database\n");
- return -1;
- }
-
- if (res) {
- read_attrs(res, flags);
- db_res_free(res);
- }
- return 1;
- }
- static int load_user_attrs(struct sip_msg* msg, unsigned long flags, fparam_t* fp)
- {
- db_res_t* res;
- if (get_str_fparam(&load_user_attrs_cmd->match[0].v.lstr, msg, (fparam_t*)fp) < 0) {
- DBG("Unable to get UID from load_user_attrs parameter\n");
- return -1;
- }
- if (db_exec(&res, load_user_attrs_cmd) < 0) {
- ERR("Error while querying database\n");
- return -1;
- }
-
- if (res) {
- read_attrs(res, flags);
- db_res_free(res);
- }
- return 1;
- }
- /*
- * Load user attributes
- */
- static int load_attrs(struct sip_msg* msg, char* fl, char* fp)
- {
- unsigned long flags;
- flags = (unsigned long)fl;
- if (flags & AVP_CLASS_URI) {
- return load_uri_attrs(msg, flags, (fparam_t*)fp);
- } else {
- return load_user_attrs(msg, flags, (fparam_t*)fp);
- }
- }
- static int attrs_fixup(void** param, int param_no)
- {
- unsigned long flags;
- char* s;
-
- if (param_no == 1) {
- /* Determine the track and class of attributes to be loaded */
- s = (char*)*param;
- flags = 0;
- if (*s != '$' || (strlen(s) != 3)) {
- ERR("Invalid parameter value, $xy expected\n");
- return -1;
- }
- switch((s[1] << 8) + s[2]) {
- case 0x4655: /* $fu */
- case 0x6675:
- case 0x4675:
- case 0x6655:
- flags = AVP_TRACK_FROM | AVP_CLASS_USER;
- break;
- case 0x4652: /* $fr */
- case 0x6672:
- case 0x4672:
- case 0x6652:
- flags = AVP_TRACK_FROM | AVP_CLASS_URI;
- break;
- case 0x5455: /* $tu */
- case 0x7475:
- case 0x5475:
- case 0x7455:
- flags = AVP_TRACK_TO | AVP_CLASS_USER;
- break;
- case 0x5452: /* $tr */
- case 0x7472:
- case 0x5472:
- case 0x7452:
- flags = AVP_TRACK_TO | AVP_CLASS_URI;
- break;
- default:
- ERR("Invalid parameter value: '%s'\n", s);
- return -1;
- }
- if ((flags & AVP_CLASS_URI) && !dm_get_did) {
- dm_get_did = (domain_get_did_t)find_export("get_did", 0, 0);
- if (!dm_get_did) {
- ERR("Domain module required but not found\n");
- return -1;
- }
- }
- pkg_free(*param);
- *param = (void*)flags;
- } else if (param_no == 2) {
- return fixup_var_str_12(param, 2);
- }
- return 0;
- }
|