lvalue.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. /*
  2. * Copyright (C) 2008 iptelorg GmbH
  3. *
  4. * Permission to use, copy, modify, and distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. /**
  17. * @file
  18. * @brief SIP-router core :: lvalues (assignment)
  19. * \ingroup core
  20. * Module: \ref core
  21. */
  22. /*
  23. * History:
  24. * --------
  25. * 2008-11-30 initial version (andrei)
  26. * 2009-04-24 delete avps after finding their new value and not before
  27. * (fixed $avp=$avp)
  28. * when assigning something undefined (e.g. non-existing avp),
  29. * delete the lvalue (similar to perl) (andrei)
  30. */
  31. #include "lvalue.h"
  32. #include "dprint.h"
  33. #include "route.h"
  34. /* callback to log assign actions */
  35. static log_assign_action_f _log_assign_action = NULL;
  36. /**
  37. * @brief set callback function log assign actions
  38. */
  39. void set_log_assign_action_cb(log_assign_action_f f)
  40. {
  41. _log_assign_action = f;
  42. }
  43. /**
  44. * @brief eval rve and assign the result to an avp
  45. *
  46. * eval rve and assign the result to an avp, lv->lv.avp=eval(rve)
  47. * based on do_action() ASSIGN_T.
  48. * @param h - script context
  49. * @param msg - sip msg
  50. * @param lv - lvalue
  51. * @param rv - rvalue expression
  52. * @return >= 0 on success (expr. bool value), -1 on error
  53. */
  54. inline static int lval_avp_assign(struct run_act_ctx* h, struct sip_msg* msg,
  55. struct lvalue* lv, struct rvalue* rv)
  56. {
  57. avp_spec_t* avp;
  58. avp_t* r_avp;
  59. avp_t* avp_mark;
  60. pv_value_t pval;
  61. int_str value;
  62. unsigned short flags;
  63. struct search_state st;
  64. int ret, v, destroy_pval;
  65. int avp_add;
  66. #if 0
  67. #define AVP_ASSIGN_NOVAL() \
  68. /* unknown value => reset the avp in function of its type */ \
  69. flags=avp->type; \
  70. if (flags & AVP_VAL_STR){ \
  71. value.s.s=""; \
  72. value.s.len=0; \
  73. }else{ \
  74. value.n=0; \
  75. }
  76. #endif
  77. #define AVP_ASSIGN_NOVAL() \
  78. /* no value => delete avp */ \
  79. avp_add=0
  80. destroy_pval=0;
  81. flags = 0;
  82. avp=&lv->lv.avps;
  83. ret=0;
  84. avp_add=1;
  85. switch(rv->type){
  86. case RV_NONE:
  87. BUG("non-intialized rval / rval expr \n");
  88. /* unknown value => reset the avp in function of its type */
  89. flags=avp->type;
  90. AVP_ASSIGN_NOVAL();
  91. ret=-1;
  92. break;
  93. case RV_INT:
  94. value.n=rv->v.l;
  95. flags=avp->type & ~AVP_VAL_STR;
  96. ret=!(!value.n);
  97. break;
  98. case RV_STR:
  99. value.s=rv->v.s;
  100. flags=avp->type | AVP_VAL_STR;
  101. ret=(value.s.len>0);
  102. break;
  103. case RV_ACTION_ST:
  104. flags=avp->type & ~AVP_VAL_STR;
  105. if (rv->v.action) {
  106. value.n=run_actions_safe(h, rv->v.action, msg);
  107. h->run_flags &= ~(RETURN_R_F|BREAK_R_F); /* catch return &
  108. break in expr*/
  109. } else
  110. value.n=-1;
  111. ret=value.n;
  112. break;
  113. case RV_BEXPR: /* logic/boolean expr. */
  114. value.n=eval_expr(h, rv->v.bexpr, msg);
  115. if (unlikely(value.n<0)){
  116. if (value.n==EXPR_DROP) /* hack to quit on drop */
  117. goto drop;
  118. WARN("error in expression\n");
  119. value.n=0; /* expr. is treated as false */
  120. }
  121. flags=avp->type & ~AVP_VAL_STR;
  122. ret=value.n;
  123. break;
  124. case RV_SEL:
  125. flags=avp->type|AVP_VAL_STR;
  126. v=run_select(&value.s, &rv->v.sel, msg);
  127. if (unlikely(v!=0)){
  128. value.s.s="";
  129. value.s.len=0;
  130. if (v<0){
  131. ret=-1;
  132. break;
  133. } /* v>0 */
  134. }
  135. ret=(value.s.len>0);
  136. break;
  137. case RV_AVP:
  138. avp_mark=0;
  139. if (unlikely((rv->v.avps.type & AVP_INDEX_ALL) == AVP_INDEX_ALL)){
  140. /* special case: add the value to the avp */
  141. r_avp = search_first_avp(rv->v.avps.type, rv->v.avps.name,
  142. &value, &st);
  143. while(r_avp){
  144. /* We take only the val type from the source avp
  145. * and reset the class, track flags and name type */
  146. flags=(avp->type & ~(AVP_INDEX_ALL|AVP_VAL_STR)) |
  147. (r_avp->flags & ~(AVP_CLASS_ALL|AVP_TRACK_ALL|
  148. AVP_NAME_STR|AVP_NAME_RE));
  149. if (add_avp_before(avp_mark, flags, avp->name, value)<0){
  150. ERR("failed to assign avp\n");
  151. ret=-1;
  152. goto error;
  153. }
  154. /* move the mark, so the next found AVP will come before
  155. the one currently added so they will have the same
  156. order as in the source list */
  157. if (avp_mark) avp_mark=avp_mark->next;
  158. else
  159. avp_mark=search_first_avp(flags, avp->name, 0, 0);
  160. r_avp=search_next_avp(&st, &value);
  161. }
  162. ret=1;
  163. goto end;
  164. }else{
  165. /* normal case, value is replaced */
  166. r_avp = search_avp_by_index(rv->v.avps.type, rv->v.avps.name,
  167. &value, rv->v.avps.index);
  168. if (likely(r_avp)){
  169. /* take only the val type from the source avp
  170. * and reset the class, track flags and name type */
  171. flags=(avp->type & ~AVP_VAL_STR) | (r_avp->flags &
  172. ~(AVP_CLASS_ALL|AVP_TRACK_ALL|AVP_NAME_STR|
  173. AVP_NAME_RE));
  174. ret=1;
  175. }else{
  176. /* on error, keep the type of the assigned avp, but
  177. reset it to an empty value */
  178. AVP_ASSIGN_NOVAL();
  179. ret=0;
  180. break;
  181. }
  182. }
  183. break;
  184. case RV_PVAR:
  185. memset(&pval, 0, sizeof(pval));
  186. if (likely(pv_get_spec_value(msg, &rv->v.pvs, &pval)==0)){
  187. destroy_pval=1;
  188. if (pval.flags & PV_TYPE_INT){
  189. value.n=pval.ri;
  190. ret=value.n;
  191. flags=avp->type & ~AVP_VAL_STR;
  192. }else if (pval.flags & PV_VAL_STR){
  193. value.s=pval.rs;
  194. ret=(value.s.len>0);
  195. flags=avp->type | AVP_VAL_STR;
  196. }else if (pval.flags==PV_VAL_NONE ||
  197. (pval.flags & (PV_VAL_NULL|PV_VAL_EMPTY))){
  198. AVP_ASSIGN_NOVAL();
  199. ret=0;
  200. }
  201. }else{
  202. /* non existing pvar */
  203. /* on error, keep the type of the assigned avp, but
  204. reset it to an empty value */
  205. AVP_ASSIGN_NOVAL();
  206. ret=0;
  207. }
  208. break;
  209. }
  210. /* If the left attr was specified without indexing brackets delete
  211. * existing AVPs before adding the new value */
  212. delete_avp(avp->type, avp->name);
  213. if (avp_add && (add_avp(flags & ~AVP_INDEX_ALL, avp->name, value) < 0)) {
  214. ERR("failed to assign value to avp\n");
  215. goto error;
  216. }
  217. end:
  218. if (destroy_pval) pv_value_destroy(&pval);
  219. return ret;
  220. error:
  221. if (destroy_pval) pv_value_destroy(&pval);
  222. return -1;
  223. drop:
  224. if (destroy_pval) pv_value_destroy(&pval);
  225. return EXPR_DROP;
  226. }
  227. /**
  228. * @brief eval rve and assign the result to a pvar
  229. *
  230. * eval rve and assign the result to a pvar, lv->lv.pvar=eval(rve)
  231. * based on do_action() ASSIGN_T.
  232. * @param h - script context
  233. * @param msg - sip msg
  234. * @param lv - lvalue
  235. * @param rv - rvalue expression
  236. * @return >= 0 on success (expr. bool value), -1 on error
  237. */
  238. inline static int lval_pvar_assign(struct run_act_ctx* h, struct sip_msg* msg,
  239. struct lvalue* lv, struct rvalue* rv)
  240. {
  241. pv_spec_t* pvar;
  242. pv_value_t pval;
  243. avp_t* r_avp;
  244. int_str avp_val;
  245. int ret;
  246. int v;
  247. int destroy_pval;
  248. #define PVAR_ASSIGN_NOVAL() \
  249. /* no value found => "undefine" */ \
  250. pv_get_null(msg, 0, &pval)
  251. destroy_pval=0;
  252. pvar=lv->lv.pvs;
  253. if (unlikely(!pv_is_w(pvar))){
  254. ERR("read only pvar\n");
  255. goto error;
  256. }
  257. memset(&pval, 0, sizeof(pval));
  258. ret=0;
  259. switch(rv->type){
  260. case RV_NONE:
  261. BUG("non-intialized rval / rval expr \n");
  262. PVAR_ASSIGN_NOVAL();
  263. ret=-1;
  264. break;
  265. case RV_INT:
  266. pval.flags=PV_TYPE_INT|PV_VAL_INT;
  267. pval.ri=rv->v.l;
  268. ret=!(!pval.ri);
  269. break;
  270. case RV_STR:
  271. pval.flags=PV_VAL_STR;
  272. pval.rs=rv->v.s;
  273. ret=(pval.rs.len>0);
  274. break;
  275. case RV_ACTION_ST:
  276. pval.flags=PV_TYPE_INT|PV_VAL_INT;
  277. if (rv->v.action) {
  278. pval.ri=run_actions_safe(h, rv->v.action, msg);
  279. h->run_flags &= ~(RETURN_R_F|BREAK_R_F); /* catch return &
  280. break in expr*/
  281. } else
  282. pval.ri=0;
  283. ret=!(!pval.ri);
  284. break;
  285. case RV_BEXPR: /* logic/boolean expr. */
  286. pval.flags=PV_TYPE_INT|PV_VAL_INT;
  287. pval.ri=eval_expr(h, rv->v.bexpr, msg);
  288. if (unlikely(pval.ri<0)){
  289. if (pval.ri==EXPR_DROP) /* hack to quit on drop */
  290. goto drop;
  291. WARN("error in expression\n");
  292. pval.ri=0; /* expr. is treated as false */
  293. }
  294. ret=!(!pval.ri);
  295. break;
  296. case RV_SEL:
  297. pval.flags=PV_VAL_STR;
  298. v=run_select(&pval.rs, &rv->v.sel, msg);
  299. if (unlikely(v!=0)){
  300. pval.flags|=PV_VAL_EMPTY;
  301. pval.rs.s="";
  302. pval.rs.len=0;
  303. if (v<0){
  304. ret=-1;
  305. break;
  306. }
  307. }
  308. ret=(pval.rs.len>0);
  309. break;
  310. case RV_AVP:
  311. r_avp = search_avp_by_index(rv->v.avps.type, rv->v.avps.name,
  312. &avp_val, rv->v.avps.index);
  313. if (likely(r_avp)){
  314. if (r_avp->flags & AVP_VAL_STR){
  315. pval.flags=PV_VAL_STR;
  316. pval.rs=avp_val.s;
  317. ret=(pval.rs.len>0);
  318. }else{
  319. pval.flags=PV_TYPE_INT|PV_VAL_INT;
  320. pval.ri=avp_val.n;
  321. ret=!(!pval.ri);
  322. }
  323. }else{
  324. PVAR_ASSIGN_NOVAL();
  325. ret=0; /* avp not defined (valid case) */
  326. break;
  327. }
  328. break;
  329. case RV_PVAR:
  330. if (likely(pv_get_spec_value(msg, &rv->v.pvs, &pval)==0)){
  331. destroy_pval=1;
  332. if (pval.flags & PV_TYPE_INT){
  333. ret=!(!pval.ri);
  334. }else if (pval.flags & PV_VAL_STR){
  335. ret=(pval.rs.len>0);
  336. }else{
  337. /* no value / not defined (e.g. avp) -> keep the flags */
  338. ret=0;
  339. }
  340. }else{
  341. ERR("non existing right pvar\n");
  342. PVAR_ASSIGN_NOVAL();
  343. ret=-1;
  344. }
  345. break;
  346. }
  347. if (unlikely(pvar->setf(msg, &pvar->pvp, EQ_T, &pval)<0)){
  348. ERR("setting pvar failed\n");
  349. goto error;
  350. }
  351. if (destroy_pval) pv_value_destroy(&pval);
  352. return ret;
  353. error:
  354. if (destroy_pval) pv_value_destroy(&pval);
  355. return -1;
  356. drop:
  357. if (destroy_pval) pv_value_destroy(&pval);
  358. return EXPR_DROP;
  359. }
  360. /** eval rve and assign the result to lv
  361. * lv=eval(rve)
  362. *
  363. * @param h - script context
  364. * @param msg - sip msg
  365. * @param lv - lvalue
  366. * @param rve - rvalue expression
  367. * @return >= 0 on success (expr. bool value), -1 on error
  368. */
  369. int lval_assign(struct run_act_ctx* h, struct sip_msg* msg,
  370. struct lvalue* lv, struct rval_expr* rve)
  371. {
  372. struct rvalue* rv;
  373. int ret;
  374. ret=0;
  375. rv=rval_expr_eval(h, msg, rve);
  376. if (unlikely(rv==0)){
  377. ERR("rval expression evaluation failed (%d,%d-%d,%d)\n",
  378. rve->fpos.s_line, rve->fpos.s_col,
  379. rve->fpos.e_line, rve->fpos.e_col);
  380. goto error;
  381. }
  382. switch(lv->type){
  383. case LV_NONE:
  384. BUG("uninitialized/invalid lvalue (%d) (cfg line: %d)\n",
  385. lv->type, rve->fpos.s_line);
  386. goto error;
  387. case LV_AVP:
  388. ret=lval_avp_assign(h, msg, lv, rv);
  389. break;
  390. case LV_PVAR:
  391. ret=lval_pvar_assign(h, msg, lv, rv);
  392. break;
  393. }
  394. if (unlikely(ret<0)){
  395. ERR("assignment failed at pos: (%d,%d-%d,%d)\n",
  396. rve->fpos.s_line, rve->fpos.s_col,
  397. rve->fpos.e_line, rve->fpos.e_col);
  398. }
  399. else
  400. {
  401. if(unlikely(_log_assign_action!=NULL))
  402. _log_assign_action(msg, lv);
  403. }
  404. rval_destroy(rv);
  405. return ret;
  406. error:
  407. if (rv) rval_destroy(rv);
  408. return -1;
  409. }