uid_avp_db.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. /*
  2. * $Id$
  3. *
  4. * Copyright (C) 2004 FhG Fokus
  5. *
  6. * This file is part of ser, a free SIP server.
  7. *
  8. * ser is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version
  12. *
  13. * For a license to use the ser software under conditions
  14. * other than those described here, or to purchase support for this
  15. * software, please contact iptel.org by e-mail at the following addresses:
  16. * [email protected]
  17. *
  18. * ser is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. * GNU General Public License for more details.
  22. *
  23. * You should have received a copy of the GNU General Public License
  24. * along with this program; if not, write to the Free Software
  25. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  26. */
  27. /*
  28. * History:
  29. * --------
  30. * 2004-06-14 added ability to read default values from DB table usr_preferences_types (kozlik)
  31. */
  32. #include <string.h>
  33. #include "../../sr_module.h"
  34. #include "../../mem/mem.h"
  35. #include "../../parser/msg_parser.h"
  36. #include "../../parser/hf.h"
  37. #include "../../parser/parse_from.h"
  38. #include "../../parser/parse_to.h"
  39. #include "../../parser/parse_uri.h"
  40. #include "../../str.h"
  41. #include "../../lib/srdb2/db.h"
  42. #include "../../config.h"
  43. #include "../../usr_avp.h"
  44. #include "../../ut.h"
  45. #include "../../id.h"
  46. #include "../uid_domain/domain.h"
  47. #include "uid_avp_db.h"
  48. #include "extra_attrs.h"
  49. MODULE_VERSION
  50. static char* db_url = DEFAULT_RODB_URL; /* Database URL */
  51. static char* user_attrs_table = "uid_user_attrs";
  52. static char* uri_attrs_table = "uid_uri_attrs";
  53. static char* uid_column = "uid";
  54. static char* username_column = "username";
  55. static char* did_column = "did";
  56. static char* name_column = "name";
  57. static char* type_column = "type";
  58. static char* val_column = "value";
  59. static char* flags_column = "flags";
  60. static char* scheme_column = "scheme";
  61. int auto_unlock = 0;
  62. db_ctx_t* ctx = 0;
  63. db_cmd_t *load_user_attrs_cmd = NULL;
  64. db_cmd_t *load_uri_attrs_cmd = NULL;
  65. static int mod_init(void);
  66. static int child_init(int);
  67. static int load_attrs(struct sip_msg* msg, char* s1, char* s2);
  68. static int attrs_fixup(void** param, int param_no);
  69. static domain_get_did_t dm_get_did = NULL;
  70. /*
  71. * Exported functions
  72. */
  73. static cmd_export_t cmds[] = {
  74. {"load_attrs", load_attrs, 2, attrs_fixup, REQUEST_ROUTE | FAILURE_ROUTE},
  75. /* functions for loading/storing flagged attributes into DB */
  76. {"load_extra_attrs", load_extra_attrs, 2, extra_attrs_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE},
  77. {"save_extra_attrs", save_extra_attrs, 2, extra_attrs_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE},
  78. {"remove_extra_attrs", remove_extra_attrs, 2, extra_attrs_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE},
  79. /* locking attrs - needed for proper work! */
  80. {"lock_extra_attrs", lock_extra_attrs, 2, extra_attrs_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE},
  81. {"unlock_extra_attrs", unlock_extra_attrs, 2, extra_attrs_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE},
  82. {0, 0, 0, 0, 0}
  83. };
  84. /*
  85. * Exported parameters
  86. */
  87. static param_export_t params[] = {
  88. {"db_url", PARAM_STRING, &db_url },
  89. {"user_attrs_table", PARAM_STRING, &user_attrs_table},
  90. {"uri_attrs_table", PARAM_STRING, &uri_attrs_table },
  91. {"uid_column", PARAM_STRING, &uid_column },
  92. {"username_column", PARAM_STRING, &username_column },
  93. {"did_column", PARAM_STRING, &did_column },
  94. {"name_column", PARAM_STRING, &name_column },
  95. {"type_column", PARAM_STRING, &type_column },
  96. {"value_column", PARAM_STRING, &val_column },
  97. {"flags_column", PARAM_STRING, &flags_column },
  98. {"scheme_column", PARAM_STRING, &scheme_column },
  99. {"attr_group", PARAM_STR | PARAM_USE_FUNC, (void*)declare_attr_group },
  100. {"auto_unlock_extra_attrs", PARAM_INT, &auto_unlock },
  101. {0, 0, 0}
  102. };
  103. struct module_exports exports = {
  104. "uid_avp_db",
  105. cmds, /* Exported commands */
  106. 0, /* RPC methods */
  107. params, /* Exported parameters */
  108. mod_init, /* module initialization function */
  109. 0, /* response function*/
  110. 0, /* destroy function */
  111. 0, /* oncancel function */
  112. child_init /* per-child init function */
  113. };
  114. static int mod_init(void)
  115. {
  116. return init_extra_avp_locks();
  117. }
  118. static int child_init(int rank)
  119. {
  120. db_fld_t res_cols[] = {
  121. {.name = name_column, .type = DB_STR},
  122. {.name = type_column, .type = DB_INT},
  123. {.name = val_column, .type = DB_STR},
  124. {.name = flags_column, .type = DB_BITMAP},
  125. {.name = NULL}
  126. };
  127. db_fld_t match_uri[] = {
  128. {.name = username_column, .type = DB_STR, .op = DB_EQ},
  129. {.name = did_column, .type = DB_STR, .op = DB_EQ},
  130. {.name = scheme_column, .type = DB_STR, .op = DB_EQ},
  131. {.name = NULL}
  132. };
  133. db_fld_t match_user[] = {
  134. {.name = uid_column, .type = DB_STR, .op = DB_EQ},
  135. {.name = NULL}
  136. };
  137. if (rank==PROC_INIT || rank==PROC_MAIN || rank==PROC_TCP_MAIN)
  138. return 0; /* do nothing for the main process */
  139. ctx = db_ctx("avp_db");
  140. if (!ctx) goto err;
  141. if (db_add_db(ctx, db_url) < 0) goto err;
  142. if (db_connect(ctx) < 0) goto err;
  143. load_uri_attrs_cmd = db_cmd(DB_GET, ctx, uri_attrs_table, res_cols, match_uri, NULL);
  144. if (!load_uri_attrs_cmd) goto err;
  145. load_user_attrs_cmd = db_cmd(DB_GET, ctx, user_attrs_table, res_cols, match_user, NULL);
  146. if (!load_user_attrs_cmd) goto err;
  147. if (init_extra_avp_queries(ctx) < 0) goto err;
  148. return 0;
  149. err:
  150. if (load_uri_attrs_cmd) db_cmd_free(load_uri_attrs_cmd);
  151. if (load_user_attrs_cmd) db_cmd_free(load_user_attrs_cmd);
  152. if (ctx) db_ctx_free(ctx);
  153. ERR("Error while initializing database layer\n");
  154. return -1;
  155. }
  156. #define IS_DB_NULL(f) (f.flags & DB_NULL)
  157. static void read_attrs(db_res_t *res, unsigned long flags)
  158. {
  159. int_str name, v;
  160. str avp_val;
  161. int type, n, found;
  162. db_rec_t* row;
  163. n = 0;
  164. found = 0;
  165. /* AVP names from DB are always strings */
  166. flags |= AVP_NAME_STR;
  167. if (res) row = db_first(res);
  168. else row = NULL;
  169. while (row) {
  170. found++;
  171. if (IS_DB_NULL(row->fld[0]) ||
  172. IS_DB_NULL(row->fld[1]) ||
  173. IS_DB_NULL(row->fld[3])) {
  174. ERR("Skipping row containing NULL entries\n");
  175. row = db_next(res);
  176. continue;
  177. }
  178. if ((row->fld[3].v.int4 & SRDB_LOAD_SER) == 0) {
  179. row = db_next(res);
  180. continue;
  181. }
  182. n++;
  183. /* Get AVP name */
  184. name.s = row->fld[0].v.lstr;
  185. /* Get AVP type */
  186. type = row->fld[1].v.int4;
  187. /* Test for NULL value */
  188. if (IS_DB_NULL(row->fld[2])) {
  189. avp_val.s = 0;
  190. avp_val.len = 0;
  191. } else {
  192. avp_val = row->fld[2].v.lstr;
  193. }
  194. if (type == AVP_VAL_STR) {
  195. /* String AVP */
  196. v.s = avp_val;
  197. flags |= AVP_VAL_STR;
  198. } else {
  199. /* Integer AVP */
  200. str2int(&avp_val, (unsigned*)&v.n);
  201. /* reset val_str as the value could be an integer */
  202. flags &= ~AVP_VAL_STR;
  203. }
  204. if (add_avp(flags, name, v) < 0) {
  205. ERR("Error while adding user attribute %.*s, skipping\n",
  206. name.s.len, ZSW(name.s.s));
  207. }
  208. row = db_next(res);
  209. }
  210. DBG("avp_db:load_attrs: %d attributes found, %d loaded\n", found, n);
  211. }
  212. static int load_uri_attrs(struct sip_msg* msg, unsigned long flags, fparam_t* fp)
  213. {
  214. db_res_t* res;
  215. str uri;
  216. struct sip_uri puri;
  217. static str default_did = STR_STATIC_INIT(DEFAULT_DID);
  218. if (get_str_fparam(&uri, msg, (fparam_t*)fp) != 0) {
  219. DBG("Unable to get URI from load_uri_attrs parameters\n");
  220. return -1;
  221. }
  222. if (parse_uri(uri.s, uri.len, &puri) < 0) {
  223. ERR("Error while parsing URI '%.*s'\n", uri.len, uri.s);
  224. return -1;
  225. }
  226. load_uri_attrs_cmd->match[0].v.lstr = puri.user;
  227. if (puri.host.len) {
  228. /* domain name is present */
  229. if (dm_get_did(&load_uri_attrs_cmd->match[1].v.lstr, &puri.host) < 0) {
  230. DBG("Cannot lookup DID for domain %.*s, using default value\n", puri.host.len, ZSW(puri.host.s));
  231. load_uri_attrs_cmd->match[1].v.lstr = default_did;
  232. }
  233. } else {
  234. /* domain name is missing -- can be caused by tel: URI */
  235. DBG("There is no domain name, using default value\n");
  236. load_uri_attrs_cmd->match[1].v.lstr = default_did;
  237. }
  238. uri_type_to_str(puri.type, &(load_uri_attrs_cmd->match[2].v.lstr));
  239. if (db_exec(&res, load_uri_attrs_cmd) < 0) {
  240. ERR("Error while querying database\n");
  241. return -1;
  242. }
  243. if (res) {
  244. read_attrs(res, flags);
  245. db_res_free(res);
  246. }
  247. return 1;
  248. }
  249. static int load_user_attrs(struct sip_msg* msg, unsigned long flags, fparam_t* fp)
  250. {
  251. db_res_t* res;
  252. if (get_str_fparam(&load_user_attrs_cmd->match[0].v.lstr, msg, (fparam_t*)fp) < 0) {
  253. DBG("Unable to get UID from load_user_attrs parameter\n");
  254. return -1;
  255. }
  256. if (db_exec(&res, load_user_attrs_cmd) < 0) {
  257. ERR("Error while querying database\n");
  258. return -1;
  259. }
  260. if (res) {
  261. read_attrs(res, flags);
  262. db_res_free(res);
  263. }
  264. return 1;
  265. }
  266. /*
  267. * Load user attributes
  268. */
  269. static int load_attrs(struct sip_msg* msg, char* fl, char* fp)
  270. {
  271. unsigned long flags;
  272. flags = (unsigned long)fl;
  273. if (flags & AVP_CLASS_URI) {
  274. return load_uri_attrs(msg, flags, (fparam_t*)fp);
  275. } else {
  276. return load_user_attrs(msg, flags, (fparam_t*)fp);
  277. }
  278. }
  279. static int attrs_fixup(void** param, int param_no)
  280. {
  281. unsigned long flags;
  282. char* s;
  283. if (param_no == 1) {
  284. /* Determine the track and class of attributes to be loaded */
  285. s = (char*)*param;
  286. flags = 0;
  287. if (*s != '$' || (strlen(s) != 3)) {
  288. ERR("Invalid parameter value, $xy expected\n");
  289. return -1;
  290. }
  291. switch((s[1] << 8) + s[2]) {
  292. case 0x4655: /* $fu */
  293. case 0x6675:
  294. case 0x4675:
  295. case 0x6655:
  296. flags = AVP_TRACK_FROM | AVP_CLASS_USER;
  297. break;
  298. case 0x4652: /* $fr */
  299. case 0x6672:
  300. case 0x4672:
  301. case 0x6652:
  302. flags = AVP_TRACK_FROM | AVP_CLASS_URI;
  303. break;
  304. case 0x5455: /* $tu */
  305. case 0x7475:
  306. case 0x5475:
  307. case 0x7455:
  308. flags = AVP_TRACK_TO | AVP_CLASS_USER;
  309. break;
  310. case 0x5452: /* $tr */
  311. case 0x7472:
  312. case 0x5472:
  313. case 0x7452:
  314. flags = AVP_TRACK_TO | AVP_CLASS_URI;
  315. break;
  316. default:
  317. ERR("Invalid parameter value: '%s'\n", s);
  318. return -1;
  319. }
  320. if ((flags & AVP_CLASS_URI) && !dm_get_did) {
  321. dm_get_did = (domain_get_did_t)find_export("get_did", 0, 0);
  322. if (!dm_get_did) {
  323. ERR("Domain module required but not found\n");
  324. return -1;
  325. }
  326. }
  327. pkg_free(*param);
  328. *param = (void*)flags;
  329. } else if (param_no == 2) {
  330. return fixup_var_str_12(param, 2);
  331. }
  332. return 0;
  333. }