cpl_loader.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. /*
  2. * $Id$
  3. *
  4. * Copyright (C) 2001-2003 FhG Fokus
  5. * Copyright (C) 2006 Voice-Sistem SRL
  6. *
  7. * This file is part of Kamailio, a free SIP server.
  8. *
  9. * Kamailio is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version
  13. *
  14. * Kamailio is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. *
  24. * History:
  25. * -------
  26. * 2003-08-21: cpl_remove() added (bogdan)
  27. * 2003-06-24: file created (bogdan)
  28. */
  29. #include <stdio.h>
  30. #include <sys/types.h>
  31. #include <sys/uio.h>
  32. #include <stdlib.h>
  33. #include <unistd.h>
  34. #include <sys/stat.h>
  35. #include <fcntl.h>
  36. #include <sys/uio.h>
  37. #include <errno.h>
  38. #include <string.h>
  39. #include <ctype.h>
  40. #include "../../str.h"
  41. #include "../../dprint.h"
  42. #include "../../mem/mem.h"
  43. #include "../../mem/shm_mem.h"
  44. #include "../../parser/parse_uri.h"
  45. #include "../../lib/kmi/mi.h"
  46. #include "cpl_db.h"
  47. #include "cpl_env.h"
  48. #include "cpl_parser.h"
  49. #include "cpl_loader.h"
  50. extern db1_con_t* db_hdl;
  51. #if 0
  52. /* debug function -> write into a file the content of a str struct. */
  53. int write_to_file(char *filename, str *buf)
  54. {
  55. int fd;
  56. int ret;
  57. fd = open(filename,O_WRONLY|O_CREAT|O_TRUNC,0644);
  58. if (!fd) {
  59. LM_ERR("cannot open file : %s\n",
  60. strerror(errno));
  61. goto error;
  62. }
  63. while ( (ret=write( fd, buf->s, buf->len))!=buf->len) {
  64. if ((ret==-1 && errno!=EINTR)|| ret!=-1) {
  65. LM_ERR("cannot write to file:"
  66. "%s write_ret=%d\n",strerror(errno), ret );
  67. goto error;
  68. }
  69. }
  70. close(fd);
  71. return 0;
  72. error:
  73. return -1;
  74. }
  75. #endif
  76. /* Loads a file into a buffer; first the file length will be determined for
  77. * allocated an exact buffer len for storing the file content into.
  78. * Returns: 1 - success
  79. * -1 - error
  80. */
  81. int load_file( char *filename, str *xml)
  82. {
  83. int n;
  84. int offset;
  85. int fd;
  86. xml->s = 0;
  87. xml->len = 0;
  88. /* open the file for reading */
  89. fd = open(filename,O_RDONLY);
  90. if (fd==-1) {
  91. LM_ERR("cannot open file for reading:"
  92. " %s\n",strerror(errno));
  93. goto error;
  94. }
  95. /* get the file length */
  96. if ( (xml->len=lseek(fd,0,SEEK_END))==-1) {
  97. LM_ERR("cannot get file length (lseek):"
  98. " %s\n", strerror(errno));
  99. goto error;
  100. }
  101. LM_DBG("file size = %d\n",xml->len);
  102. if ( lseek(fd,0,SEEK_SET)==-1 ) {
  103. LM_ERR("cannot go to beginning (lseek):"
  104. " %s\n",strerror(errno));
  105. goto error;
  106. }
  107. /* get some memory */
  108. xml->s = (char*)pkg_malloc( xml->len+1/*null terminated*/ );
  109. if (!xml->s) {
  110. LM_ERR("no more free pkg memory\n");
  111. goto error;
  112. }
  113. /*start reading */
  114. offset = 0;
  115. while ( offset<xml->len ) {
  116. n=read( fd, xml->s+offset, xml->len-offset);
  117. if (n==-1) {
  118. if (errno!=EINTR) {
  119. LM_ERR("read failed:"
  120. " %s\n", strerror(errno));
  121. goto error;
  122. }
  123. } else {
  124. if (n==0) break;
  125. offset += n;
  126. }
  127. }
  128. if (xml->len!=offset) {
  129. LM_ERR("couldn't read all file!\n");
  130. goto error;
  131. }
  132. xml->s[xml->len] = 0;
  133. close(fd);
  134. return 1;
  135. error:
  136. if (fd!=-1) close(fd);
  137. if (xml->s) pkg_free( xml->s);
  138. return -1;
  139. }
  140. /* Writes an array of texts into the given response file.
  141. * Accepts also empty texts, case in which it will be created an empty
  142. * response file.
  143. */
  144. void write_to_file( char *file, str *txt, int n )
  145. {
  146. int fd;
  147. /* open file for write */
  148. fd = open( file, O_WRONLY|O_CREAT|O_TRUNC/*|O_NOFOLLOW*/, 0600 );
  149. if (fd==-1) {
  150. LM_ERR("cannot open response file "
  151. "<%s>: %s\n", file, strerror(errno));
  152. return;
  153. }
  154. /* write the txt, if any */
  155. if (n>0) {
  156. again:
  157. if ( writev( fd, (struct iovec*)txt, n)==-1) {
  158. if (errno==EINTR) {
  159. goto again;
  160. } else {
  161. LM_ERR("write_logs_to_file: writev failed: "
  162. "%s\n", strerror(errno) );
  163. }
  164. }
  165. }
  166. /* close the file*/
  167. close( fd );
  168. return;
  169. }
  170. /**************************** MI ****************************/
  171. #define FILE_LOAD_ERR_S "Cannot read CPL file"
  172. #define FILE_LOAD_ERR_LEN (sizeof(FILE_LOAD_ERR_S)-1)
  173. #define DB_SAVE_ERR_S "Cannot save CPL to database"
  174. #define DB_SAVE_ERR_LEN (sizeof(DB_SAVE_ERR_S)-1)
  175. #define CPLFILE_ERR_S "Bad CPL file"
  176. #define CPLFILE_ERR_LEN (sizeof(CPLFILE_ERR_S)-1)
  177. #define USRHOST_ERR_S "Bad user@host"
  178. #define USRHOST_ERR_LEN (sizeof(USRHOST_ERR_S)-1)
  179. #define DB_RMV_ERR_S "Database remove failed"
  180. #define DB_RMV_ERR_LEN (sizeof(DB_RMV_ERR_S)-1)
  181. #define DB_GET_ERR_S "Database query failed"
  182. #define DB_GET_ERR_LEN (sizeof(DB_GET_ERR_S)-1)
  183. struct mi_root* mi_cpl_load(struct mi_root *cmd_tree, void *param)
  184. {
  185. struct mi_root *rpl_tree;
  186. struct mi_node *cmd;
  187. struct sip_uri uri;
  188. str xml = {0,0};
  189. str bin = {0,0};
  190. str enc_log = {0,0};
  191. str val;
  192. char *file;
  193. LM_DBG("\"LOAD_CPL\" MI command received!\n");
  194. cmd = &cmd_tree->node;
  195. /* check user+host */
  196. if((cmd->kids==NULL) ||(cmd->kids->next==NULL) || (cmd->kids->next->next))
  197. return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
  198. val = cmd->kids->value;
  199. if (parse_uri( val.s, val.len, &uri)!=0){
  200. LM_ERR("invalid sip URI [%.*s]\n",
  201. val.len, val.s);
  202. return init_mi_tree( 400, USRHOST_ERR_S, USRHOST_ERR_LEN );
  203. }
  204. LM_DBG("user@host=%.*s@%.*s\n",
  205. uri.user.len,uri.user.s,uri.host.len,uri.host.s);
  206. /* second argument is the cpl file */
  207. val = cmd->kids->next->value;
  208. file = pkg_malloc(val.len+1);
  209. if (file==NULL) {
  210. LM_ERR("no more pkg mem\n");
  211. return 0;
  212. }
  213. memcpy( file, val.s, val.len);
  214. file[val.len]= '\0';
  215. /* load the xml file - this function will allocated a buff for the loading
  216. * the cpl file and attach it to xml.s -> don't forget to free it! */
  217. if (load_file( file, &xml)!=1) {
  218. pkg_free(file);
  219. return init_mi_tree( 500, FILE_LOAD_ERR_S, FILE_LOAD_ERR_LEN );
  220. }
  221. LM_DBG("cpl file=%s loaded\n",file);
  222. pkg_free(file);
  223. /* get the binary coding for the XML file */
  224. if (encodeCPL( &xml, &bin, &enc_log)!=1) {
  225. rpl_tree = init_mi_tree( 500, CPLFILE_ERR_S, CPLFILE_ERR_LEN );
  226. goto error;
  227. }
  228. /* write both the XML and binary formats into database */
  229. if (write_to_db( &uri.user,cpl_env.use_domain?&uri.host:0, &xml, &bin)!=1){
  230. rpl_tree = init_mi_tree( 500, DB_SAVE_ERR_S, DB_SAVE_ERR_LEN );
  231. goto error;
  232. }
  233. /* everything was OK */
  234. rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
  235. error:
  236. if (rpl_tree && enc_log.len)
  237. add_mi_node_child(&rpl_tree->node,MI_DUP_VALUE,"Log",3,enc_log.s,enc_log.len);
  238. if (enc_log.s)
  239. pkg_free ( enc_log.s );
  240. if (xml.s)
  241. pkg_free ( xml.s );
  242. return rpl_tree;
  243. }
  244. struct mi_root * mi_cpl_remove(struct mi_root *cmd_tree, void *param)
  245. {
  246. struct mi_node *cmd;
  247. struct sip_uri uri;
  248. str user;
  249. LM_DBG("\"REMOVE_CPL\" MI command received!\n");
  250. cmd = &cmd_tree->node;
  251. /* check if there is only one parameter*/
  252. if(!(cmd->kids && cmd->kids->next== NULL))
  253. return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
  254. user = cmd->kids->value;
  255. /* check user+host */
  256. if (parse_uri( user.s, user.len, &uri)!=0){
  257. LM_ERR("invalid SIP uri [%.*s]\n",
  258. user.len,user.s);
  259. return init_mi_tree( 400, USRHOST_ERR_S, USRHOST_ERR_LEN );
  260. }
  261. LM_DBG("user@host=%.*s@%.*s\n",
  262. uri.user.len,uri.user.s,uri.host.len,uri.host.s);
  263. if (rmv_from_db( &uri.user, cpl_env.use_domain?&uri.host:0)!=1)
  264. return init_mi_tree( 500, DB_RMV_ERR_S, DB_RMV_ERR_LEN );
  265. return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
  266. }
  267. struct mi_root * mi_cpl_get(struct mi_root *cmd_tree, void *param)
  268. {
  269. struct mi_node *cmd;
  270. struct sip_uri uri;
  271. struct mi_root* rpl_tree;
  272. str script = {0,0};
  273. str user;
  274. cmd = &cmd_tree->node;
  275. /* check if there is only one parameter*/
  276. if(!(cmd->kids && cmd->kids->next== NULL))
  277. return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
  278. /* check user+host */
  279. user = cmd->kids->value;
  280. if (parse_uri( user.s, user.len, &uri)!=0) {
  281. LM_ERR("invalid user@host [%.*s]\n",
  282. user.len,user.s);
  283. return init_mi_tree( 400, USRHOST_ERR_S, USRHOST_ERR_LEN );
  284. }
  285. LM_DBG("user@host=%.*s@%.*s\n",
  286. uri.user.len,uri.user.s,uri.host.len,uri.host.s);
  287. /* get the script for this user */
  288. str query_str = str_init("cpl_xml");
  289. if (get_user_script( &uri.user, cpl_env.use_domain?&uri.host:0,
  290. &script, &query_str)==-1)
  291. return init_mi_tree( 500, DB_GET_ERR_S, DB_GET_ERR_LEN );
  292. /* write the response into response file - even if script is null */
  293. rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
  294. if (rpl_tree!=NULL)
  295. add_mi_node_child( &rpl_tree->node, MI_DUP_VALUE, 0, 0,
  296. script.s, script.len);
  297. if (script.s)
  298. shm_free( script.s );
  299. return rpl_tree;
  300. }