2
0

xhttp_mod.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. /*
  2. * $Id$
  3. *
  4. * Copyright (C) 2010 Daniel-Constantin Mierla (asipto.com)
  5. *
  6. * This file is part of Kamailio, a free SIP server.
  7. *
  8. * Kamailio 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. * Kamailio is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21. *
  22. */
  23. #include <string.h>
  24. #include <stdlib.h>
  25. #include <stdio.h>
  26. #include "../../sr_module.h"
  27. #include "../../error.h"
  28. #include "../../mem/mem.h"
  29. #include "../../ut.h"
  30. #include "../../dset.h"
  31. #include "../../dprint.h"
  32. #include "../../data_lump.h"
  33. #include "../../data_lump_rpl.h"
  34. #include "../../receive.h"
  35. #include "../../msg_translator.h"
  36. #include "../../modules/sl/sl.h"
  37. #include "../../nonsip_hooks.h"
  38. #include "../../action.h"
  39. #include "../../script_cb.h"
  40. #include "../../route.h"
  41. #include "../../sip_msg_clone.h"
  42. #include "../../mod_fix.h"
  43. #include "../../pvar.h"
  44. #include "api.h"
  45. #include "xhttp_trans.h"
  46. MODULE_VERSION
  47. static int xhttp_handler(sip_msg_t* msg);
  48. static int w_xhttp_send_reply(sip_msg_t* msg, char* pcode, char* preason,
  49. char *pctype, char* pbody);
  50. static int mod_init(void);
  51. static int fixup_xhttp_reply(void** param, int param_no);
  52. static int pv_get_huri(struct sip_msg *msg, pv_param_t *param,
  53. pv_value_t *res);
  54. static int xhttp_route_no=DEFAULT_RT;
  55. static char* xhttp_url_match = NULL;
  56. static regex_t xhttp_url_match_regexp;
  57. static char* xhttp_url_skip = NULL;
  58. static regex_t xhttp_url_skip_regexp;
  59. /** SL API structure */
  60. sl_api_t slb;
  61. static cmd_export_t cmds[] = {
  62. {"xhttp_reply", (cmd_function)w_xhttp_send_reply,
  63. 4, fixup_xhttp_reply, 0, REQUEST_ROUTE},
  64. {"bind_xhttp", (cmd_function)bind_xhttp,
  65. 0, 0, 0, ANY_ROUTE},
  66. {0, 0, 0, 0, 0}
  67. };
  68. static pv_export_t mod_pvs[] = {
  69. {{"hu", (sizeof("hu")-1)}, /* */
  70. PVT_OTHER, pv_get_huri, 0,
  71. 0, 0, 0, 0},
  72. { {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
  73. };
  74. static param_export_t params[] = {
  75. {"url_match", PARAM_STRING, &xhttp_url_match},
  76. {"url_skip", PARAM_STRING, &xhttp_url_skip},
  77. {0, 0, 0}
  78. };
  79. /** module exports */
  80. struct module_exports exports= {
  81. "xhttp",
  82. DEFAULT_DLFLAGS, /* dlopen flags */
  83. cmds,
  84. params,
  85. 0, /* exported statistics */
  86. 0 , /* exported MI functions */
  87. mod_pvs, /* exported pseudo-variables */
  88. 0, /* extra processes */
  89. mod_init, /* module initialization function */
  90. 0,
  91. 0,
  92. 0 /* per-child init function */
  93. };
  94. static tr_export_t mod_trans[] = {
  95. { {"url", sizeof("url")-1},
  96. xhttp_tr_parse_url },
  97. { { 0, 0 }, 0 }
  98. };
  99. /**
  100. *
  101. */
  102. static int mod_init(void)
  103. {
  104. struct nonsip_hook nsh;
  105. int route_no;
  106. route_no=route_get(&event_rt, "xhttp:request");
  107. if (route_no==-1)
  108. {
  109. LM_ERR("failed to find event_route[xhttp:request]\n");
  110. return -1;
  111. }
  112. if (event_rt.rlist[route_no]==0)
  113. {
  114. LM_WARN("event_route[xhttp:request] is empty\n");
  115. }
  116. xhttp_route_no=route_no;
  117. /* bind the SL API */
  118. if (sl_load_api(&slb)!=0) {
  119. LM_ERR("cannot bind to SL API\n");
  120. return -1;
  121. }
  122. /* register non-sip hooks */
  123. memset(&nsh, 0, sizeof(nsh));
  124. nsh.name = "xhttp";
  125. nsh.destroy = 0;
  126. nsh.on_nonsip_req = xhttp_handler;
  127. if (register_nonsip_msg_hook(&nsh)<0)
  128. {
  129. LM_ERR("Failed to register non sip msg hooks\n");
  130. return -1;
  131. }
  132. if(xhttp_url_match!=NULL)
  133. {
  134. memset(&xhttp_url_match_regexp, 0, sizeof(regex_t));
  135. if (regcomp(&xhttp_url_match_regexp, xhttp_url_match, REG_EXTENDED)!=0) {
  136. LM_ERR("bad match re %s\n", xhttp_url_match);
  137. return E_BAD_RE;
  138. }
  139. }
  140. if(xhttp_url_skip!=NULL)
  141. {
  142. memset(&xhttp_url_skip_regexp, 0, sizeof(regex_t));
  143. if (regcomp(&xhttp_url_skip_regexp, xhttp_url_skip, REG_EXTENDED)!=0) {
  144. LM_ERR("bad skip re %s\n", xhttp_url_skip);
  145. return E_BAD_RE;
  146. }
  147. }
  148. return 0;
  149. }
  150. int mod_register(char *path, int *dlflags, void *p1, void *p2)
  151. {
  152. return register_trans_mod(path, mod_trans);
  153. }
  154. /**
  155. *
  156. */
  157. static int pv_get_huri(struct sip_msg *msg, pv_param_t *param,
  158. pv_value_t *res)
  159. {
  160. if(msg==NULL || res==NULL)
  161. return -1;
  162. return pv_get_strval(msg, param, res, &msg->first_line.u.request.uri);
  163. }
  164. /**
  165. *
  166. */
  167. static char* xhttp_to_sip(sip_msg_t* msg, int* new_msg_len)
  168. {
  169. unsigned int len, via_len;
  170. char* via, *new_msg, *p;
  171. str ip, port;
  172. struct hostport hp;
  173. struct dest_info dst;
  174. ip.s = ip_addr2a(&msg->rcv.src_ip);
  175. ip.len = strlen(ip.s);
  176. port.s = int2str(msg->rcv.src_port, &port.len);
  177. hp.host = &ip;
  178. hp.port = &port;
  179. init_dst_from_rcv(&dst, &msg->rcv);
  180. via = via_builder(&via_len, &dst, 0, 0, &hp);
  181. if (via == 0)
  182. {
  183. LM_DBG("failed to build via\n");
  184. return 0;
  185. }
  186. len = via_len + msg->len;
  187. p = new_msg = pkg_malloc(len + 1);
  188. if (new_msg == 0)
  189. {
  190. LM_DBG("memory allocation failure (%d bytes)\n", len);
  191. pkg_free(via);
  192. return 0;
  193. }
  194. /* new message:
  195. * <orig first line>
  196. * Via: <faked via>
  197. * <orig http message w/o the first line>
  198. */
  199. memcpy(p, msg->first_line.u.request.method.s,
  200. msg->first_line.len);
  201. p += msg->first_line.len;
  202. memcpy(p, via, via_len);
  203. p += via_len;
  204. memcpy(p, SIP_MSG_START(msg) + msg->first_line.len,
  205. msg->len - msg->first_line.len);
  206. new_msg[len] = 0;
  207. pkg_free(via);
  208. *new_msg_len = len;
  209. return new_msg;
  210. }
  211. /**
  212. *
  213. */
  214. static int xhttp_process_request(sip_msg_t* orig_msg,
  215. char* new_buf, unsigned int new_len)
  216. {
  217. int ret;
  218. sip_msg_t tmp_msg, *msg;
  219. struct run_act_ctx ra_ctx;
  220. ret=0;
  221. if (new_buf && new_len)
  222. {
  223. memset(&tmp_msg, 0, sizeof(sip_msg_t));
  224. tmp_msg.buf = new_buf;
  225. tmp_msg.len = new_len;
  226. tmp_msg.rcv = orig_msg->rcv;
  227. tmp_msg.id = orig_msg->id;
  228. tmp_msg.set_global_address = orig_msg->set_global_address;
  229. tmp_msg.set_global_port = orig_msg->set_global_port;
  230. if (parse_msg(new_buf, new_len, &tmp_msg) != 0)
  231. {
  232. LM_ERR("parse_msg failed\n");
  233. goto error;
  234. }
  235. msg = &tmp_msg;
  236. } else {
  237. msg = orig_msg;
  238. }
  239. if ((msg->first_line.type != SIP_REQUEST) || (msg->via1 == 0) ||
  240. (msg->via1->error != PARSE_OK))
  241. {
  242. LM_CRIT("strange message: %.*s\n", msg->len, msg->buf);
  243. goto error;
  244. }
  245. if (exec_pre_script_cb(msg, REQUEST_CB_TYPE) == 0)
  246. {
  247. goto done;
  248. }
  249. init_run_actions_ctx(&ra_ctx);
  250. if (run_actions(&ra_ctx, event_rt.rlist[xhttp_route_no], msg) < 0)
  251. {
  252. ret=-1;
  253. LM_DBG("error while trying script\n");
  254. goto done;
  255. }
  256. done:
  257. exec_post_script_cb(msg, REQUEST_CB_TYPE);
  258. if (msg != orig_msg)
  259. {
  260. free_sip_msg(msg);
  261. }
  262. return ret;
  263. error:
  264. return -1;
  265. }
  266. /**
  267. *
  268. */
  269. static int xhttp_handler(sip_msg_t* msg)
  270. {
  271. int ret;
  272. char* fake_msg;
  273. int fake_msg_len;
  274. regmatch_t pmatch;
  275. char c;
  276. ret=NONSIP_MSG_DROP;
  277. if(!IS_HTTP(msg))
  278. {
  279. /* oly http msg type */
  280. return NONSIP_MSG_PASS;
  281. }
  282. if(xhttp_url_skip!=NULL || xhttp_url_match!=NULL)
  283. {
  284. c = msg->first_line.u.request.uri.s[msg->first_line.u.request.uri.len];
  285. msg->first_line.u.request.uri.s[msg->first_line.u.request.uri.len]
  286. = '\0';
  287. if (xhttp_url_skip!=NULL &&
  288. regexec(&xhttp_url_skip_regexp, msg->first_line.u.request.uri.s,
  289. 1, &pmatch, 0)==0)
  290. {
  291. LM_DBG("URL matched skip re\n");
  292. msg->first_line.u.request.uri.s[msg->first_line.u.request.uri.len]
  293. = c;
  294. return NONSIP_MSG_PASS;
  295. }
  296. if (xhttp_url_match!=NULL &&
  297. regexec(&xhttp_url_match_regexp, msg->first_line.u.request.uri.s,
  298. 1, &pmatch, 0)!=0)
  299. {
  300. LM_DBG("URL not matched\n");
  301. msg->first_line.u.request.uri.s[msg->first_line.u.request.uri.len]
  302. = c;
  303. return NONSIP_MSG_PASS;
  304. }
  305. msg->first_line.u.request.uri.s[msg->first_line.u.request.uri.len] = c;
  306. }
  307. if (msg->via1 == 0)
  308. {
  309. fake_msg = xhttp_to_sip(msg, &fake_msg_len);
  310. if (fake_msg == 0)
  311. {
  312. LM_ERR("out of memory\n");
  313. ret=NONSIP_MSG_ERROR;
  314. } else {
  315. DBG("new fake msg created (%d bytes):\n<%.*s>\n",
  316. fake_msg_len, fake_msg_len, fake_msg);
  317. if (xhttp_process_request(msg, fake_msg, fake_msg_len)<0)
  318. ret=NONSIP_MSG_ERROR;
  319. pkg_free(fake_msg);
  320. }
  321. return ret;
  322. } else {
  323. LM_DBG("http msg unchanged (%d bytes):\n<%.*s>\n",
  324. msg->len, msg->len, msg->buf);
  325. if (xhttp_process_request(msg, 0, 0)<0)
  326. ret=NONSIP_MSG_ERROR;
  327. return ret;
  328. }
  329. }
  330. /**
  331. *
  332. */
  333. static int xhttp_send_reply(sip_msg_t *msg, int code, str *reason,
  334. str *ctype, str *body)
  335. {
  336. str tbuf;
  337. if(ctype!=NULL && ctype->len>0)
  338. {
  339. /* add content-type */
  340. tbuf.len=sizeof("Content-Type: ") - 1 + ctype->len + CRLF_LEN;
  341. tbuf.s=pkg_malloc(sizeof(char)*(tbuf.len));
  342. if (tbuf.s==0)
  343. {
  344. LM_ERR("out of pkg memory\n");
  345. return -1;
  346. }
  347. memcpy(tbuf.s, "Content-Type: ", sizeof("Content-Type: ") - 1);
  348. memcpy(tbuf.s+sizeof("Content-Type: ") - 1, ctype->s, ctype->len);
  349. memcpy(tbuf.s+sizeof("Content-Type: ") - 1 + ctype->len,
  350. CRLF, CRLF_LEN);
  351. if (add_lump_rpl(msg, tbuf.s, tbuf.len, LUMP_RPL_HDR) == 0)
  352. {
  353. LM_ERR("failed to insert content-type lump\n");
  354. pkg_free(tbuf.s);
  355. return -1;
  356. }
  357. pkg_free(tbuf.s);
  358. }
  359. if(body!=NULL && body->len>0)
  360. {
  361. if (add_lump_rpl(msg, body->s, body->len, LUMP_RPL_BODY) < 0)
  362. {
  363. LM_ERR("Error while adding reply lump\n");
  364. return -1;
  365. }
  366. }
  367. if (slb.freply(msg, code, reason) < 0)
  368. {
  369. LM_ERR("Error while sending reply\n");
  370. return -1;
  371. }
  372. return 0;
  373. }
  374. /**
  375. *
  376. */
  377. static int w_xhttp_send_reply(sip_msg_t* msg, char* pcode, char* preason,
  378. char *pctype, char* pbody)
  379. {
  380. str body = {0, 0};
  381. str reason = {"OK", 2};
  382. str ctype = {"text/plain", 10};
  383. int code = 200;
  384. if(pcode==0 || preason==0 || pctype==0 || pbody==0)
  385. {
  386. LM_ERR("invalid parameters\n");
  387. return -1;
  388. }
  389. if(fixup_get_ivalue(msg, (gparam_p)pcode, &code)!=0)
  390. {
  391. LM_ERR("no reply code value\n");
  392. return -1;
  393. }
  394. if(code<100 || code>700)
  395. {
  396. LM_ERR("invalid code parameter\n");
  397. return -1;
  398. }
  399. if(fixup_get_svalue(msg, (gparam_p)preason, &reason)!=0)
  400. {
  401. LM_ERR("unable to get reason\n");
  402. return -1;
  403. }
  404. if(reason.s==NULL || reason.len == 0)
  405. {
  406. LM_ERR("invalid reason parameter\n");
  407. return -1;
  408. }
  409. if(fixup_get_svalue(msg, (gparam_p)pctype, &ctype)!=0)
  410. {
  411. LM_ERR("unable to get content type\n");
  412. return -1;
  413. }
  414. if(ctype.s==NULL)
  415. {
  416. LM_ERR("invalid content-type parameter\n");
  417. return -1;
  418. }
  419. if(fixup_get_svalue(msg, (gparam_p)pbody, &body)!=0)
  420. {
  421. LM_ERR("unable to get body\n");
  422. return -1;
  423. }
  424. if(body.s==NULL)
  425. {
  426. LM_ERR("invalid body parameter\n");
  427. return -1;
  428. }
  429. if(xhttp_send_reply(msg, code, &reason, &ctype, &body)<0)
  430. return -1;
  431. return 1;
  432. }
  433. /**
  434. *
  435. */
  436. static int fixup_xhttp_reply(void** param, int param_no)
  437. {
  438. if (param_no == 1) {
  439. return fixup_igp_null(param, 1);
  440. } else if (param_no == 2) {
  441. return fixup_spve_null(param, 1);
  442. } else if (param_no == 3) {
  443. return fixup_spve_null(param, 1);
  444. } else if (param_no == 4) {
  445. return fixup_spve_null(param, 1);
  446. }
  447. return 0;
  448. }
  449. /**
  450. *
  451. */
  452. int bind_xhttp(xhttp_api_t* api)
  453. {
  454. if (!api) {
  455. ERR("Invalid parameter value\n");
  456. return -1;
  457. }
  458. api->reply = xhttp_send_reply;
  459. return 0;
  460. }
  461. /** @} */