1 /*
2 * Copyright (C) 2001-2003 FhG Fokus
3 *
4 * This file is part of Kamailio, a free SIP server.
5 *
6 * Kamailio is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version
10 *
11 * Kamailio is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 /*!
22 * \file
23 * \brief Kamailio core :: PV API specification
24 * \ingroup core
25 * Module: \ref core
26 */
27
28
29 #include <stdio.h>
30 #include <string.h>
31 #include <sys/types.h>
32 #include <unistd.h>
33
34 #include "mem/mem.h"
35 #include "mem/shm_mem.h"
36 #include "ut.h"
37 #include "dprint.h"
38 #include "hashes.h"
39 #include "route.h"
40 #include "pvapi.h"
41 #include "pvar.h"
42
43 #define PV_TABLE_SIZE 512 /*!< pseudo-variables table size */
44 #define TR_TABLE_SIZE 256 /*!< transformations table size */
45
46
47 void tr_destroy(trans_t *t);
48 void tr_free(trans_t *t);
49
50 typedef struct _pv_item
51 {
52 pv_export_t pve;
53 unsigned int pvid;
54 struct _pv_item *next;
55 } pv_item_t, *pv_item_p;
56
57 static pv_item_t* _pv_table[PV_TABLE_SIZE];
58 static int _pv_table_set = 0;
59
60 static pv_cache_t* _pv_cache[PV_CACHE_SIZE];
61 static int _pv_cache_set = 0;
62 static int _pv_cache_counter = 0;
63 static int _pv_cache_drop_index = 0;
64
65 /**
66 *
67 */
pv_init_table(void)68 void pv_init_table(void)
69 {
70 memset(_pv_table, 0, sizeof(pv_item_t*)*PV_TABLE_SIZE);
71 _pv_table_set = 1;
72 }
73
74 /**
75 *
76 */
pv_init_cache(void)77 void pv_init_cache(void)
78 {
79 memset(_pv_cache, 0, sizeof(pv_cache_t*)*PV_CACHE_SIZE);
80 _pv_cache_set = 1;
81 }
82
83 /**
84 *
85 */
pv_cache_get_table(void)86 pv_cache_t **pv_cache_get_table(void)
87 {
88 if(_pv_cache_set==1) return _pv_cache;
89 return NULL;
90 }
91
92 /**
93 * @brief Check if a char is valid according to the PV syntax
94 * @param c checked char
95 * @return 1 if char is valid, 0 if not valid
96 */
is_pv_valid_char(char c)97 static int is_pv_valid_char(char c)
98 {
99 if((c>='0' && c<='9') || (c>='a' && c<='z') || (c>='A' && c<='Z')
100 || (c=='_') || (c=='.') || (c=='?') /* ser $? */)
101 return 1;
102 return 0;
103 }
104
105 /**
106 *
107 */
pv_locate_name(str * in)108 int pv_locate_name(str *in)
109 {
110 int i;
111 int pcount;
112
113 if(in==NULL || in->s==NULL || in->len<2)
114 {
115 LM_ERR("bad parameters\n");
116 return -1;
117 }
118
119 if(in->s[0]!=PV_MARKER)
120 {
121 LM_ERR("missing pv marker [%.*s]\n", in->len, in->s);
122 return -1;
123 }
124 if(in->s[1]==PV_MARKER)
125 {
126 return 2;
127 }
128 pcount = 0;
129 if(in->s[1]==PV_LNBRACKET)
130 {
131 /* name with parenthesis: $(...) */
132 pcount = 1;
133 for(i=2; i<in->len; i++)
134 {
135 if(in->s[i]==PV_LNBRACKET)
136 pcount++;
137 else if(in->s[i]==PV_RNBRACKET)
138 pcount--;
139 if(pcount==0)
140 return i+1;
141 }
142 /* non-closing name parenthesis */
143 LM_ERR("non-closing name parenthesis [%.*s]\n",in->len,in->s);
144 return -1;
145 }
146
147 /* name without parenthesis: $xyz(...) */
148 for(i=1; i<in->len; i++)
149 {
150 if(!is_pv_valid_char(in->s[i]))
151 {
152 if(in->s[i]==PV_LNBRACKET)
153 {
154 /* inner-name parenthesis */
155 pcount = 1;
156 break;
157 } else {
158 return i;
159 }
160 }
161 }
162 if(pcount==0)
163 return i;
164
165 i++;
166 for( ; i<in->len; i++)
167 {
168 if(in->s[i]==PV_LNBRACKET)
169 pcount++;
170 else if(in->s[i]==PV_RNBRACKET)
171 pcount--;
172 if(pcount==0)
173 return i+1;
174 }
175 /* non-closing inner-name parenthesis */
176 LM_ERR("non-closing inner-name parenthesis [%.*s]\n",in->len,in->s);
177 return -1;
178 }
179
180 /**
181 *
182 */
pv_table_add(pv_export_t * e)183 int pv_table_add(pv_export_t *e)
184 {
185 char *p;
186 str *in;
187 pv_item_t *pvi = NULL;
188 pv_item_t *pvj = NULL;
189 pv_item_t *pvn = NULL;
190 int found;
191 unsigned int pvid;
192
193 if(e==NULL || e->name.s==NULL || e->getf==NULL || e->type==PVT_NONE)
194 {
195 LM_ERR("invalid parameters\n");
196 return -1;
197 }
198
199 if(_pv_table_set==0)
200 {
201 LM_DBG("PV table not initialized, doing it now\n");
202 pv_init_table();
203 }
204 in = &(e->name);
205 p = in->s;
206 while(is_in_str(p,in) && is_pv_valid_char(*p))
207 p++;
208 if(is_in_str(p,in))
209 {
210 LM_ERR("invalid char [%c] in [%.*s]\n", *p, in->len, in->s);
211 return -1;
212 }
213 found = 0;
214 //pvid = get_hash1_raw(in->s, in->len);
215 pvid = get_hash1_raw(in->s, in->len);
216
217 pvi = _pv_table[pvid%PV_TABLE_SIZE];
218 while(pvi)
219 {
220 if(pvi->pvid > pvid)
221 break;
222 if(pvi->pve.name.len==in->len)
223 {
224 found = strncmp(pvi->pve.name.s, in->s, in->len);
225
226 if(found==0)
227 {
228 LM_ERR("pvar [%.*s] already exists\n", in->len, in->s);
229 return -1;
230 }
231 }
232 pvj = pvi;
233 pvi = pvi->next;
234 }
235
236 pvn = (pv_item_t*)pkg_malloc(sizeof(pv_item_t));
237 if(pvn==0)
238 {
239 PKG_MEM_ERROR;
240 return -1;
241 }
242 memset(pvn, 0, sizeof(pv_item_t));
243 memcpy(&(pvn->pve), e, sizeof(pv_export_t));
244 pvn->pvid = pvid;
245
246 if(pvj==0)
247 {
248 pvn->next = _pv_table[pvid%PV_TABLE_SIZE];
249 _pv_table[pvid%PV_TABLE_SIZE] = pvn;
250 goto done;
251 }
252 pvn->next = pvj->next;
253 pvj->next = pvn;
254
255 done:
256 return 0;
257 }
258
259 /**
260 *
261 */
pv_cache_drop(void)262 int pv_cache_drop(void)
263 {
264 int i;
265 pv_cache_t *pvp;
266 pv_cache_t *pvi;
267
268 if(_pv_cache_set==0) {
269 LM_DBG("PV cache not initialized\n");
270 return 0;
271 }
272 /* round-robin on slots to find a $sht(...) to drop */
273 _pv_cache_drop_index = (_pv_cache_drop_index + 1) % PV_CACHE_SIZE;
274 for(i=_pv_cache_drop_index; i<PV_CACHE_SIZE; i++) {
275 pvi = _pv_cache[i];
276 pvp = NULL;
277 while(pvi) {
278 if(pvi->pvname.len>5 && strncmp(pvi->pvname.s, "$sht(", 5)==0) {
279 LM_DBG("dropping from pv cache [%d]: %.*s\n", i,
280 pvi->pvname.len, pvi->pvname.s);
281 if(pvp) {
282 pvp->next = pvi->next;
283 } else {
284 _pv_cache[i] = pvi->next;
285 }
286 if(pvi->spec.pvp.pvn.nfree) {
287 pvi->spec.pvp.pvn.nfree((void*)(&pvi->spec.pvp.pvn));
288 }
289 pkg_free(pvi);
290 _pv_cache_counter--;
291 return 1;
292 }
293 pvp = pvi;
294 pvi = pvi->next;
295 }
296 }
297 for(i=0; i<_pv_cache_drop_index; i++) {
298 pvi = _pv_cache[i];
299 pvp = NULL;
300 while(pvi) {
301 if(pvi->pvname.len>5 && strncmp(pvi->pvname.s, "$sht(", 5)==0) {
302 LM_DBG("dropping from pv cache [%d]: %.*s\n", i,
303 pvi->pvname.len, pvi->pvname.s);
304 if(pvp) {
305 pvp->next = pvi->next;
306 } else {
307 _pv_cache[i] = pvi->next;
308 }
309 if(pvi->spec.pvp.pvn.nfree) {
310 pvi->spec.pvp.pvn.nfree((void*)(&pvi->spec.pvp.pvn));
311 }
312 pkg_free(pvi);
313 _pv_cache_counter--;
314 return 1;
315 }
316 pvp = pvi;
317 pvi = pvi->next;
318 }
319 }
320 LM_WARN("no suitable variable found to drop from pv cache\n");
321 return 0;
322 }
323
324 /**
325 *
326 */
pv_cache_add(str * name)327 pv_spec_t* pv_cache_add(str *name)
328 {
329 pv_cache_t *pvn;
330 unsigned int pvid;
331 char *p;
332
333 if(_pv_cache_set==0)
334 {
335 LM_DBG("PV cache not initialized, doing it now\n");
336 pv_init_cache();
337 }
338 if(_pv_cache_counter+1>=cfg_get(core, core_cfg, pv_cache_limit)) {
339 if(_pv_cache_counter+1==cfg_get(core, core_cfg, pv_cache_limit)) {
340 LM_WARN("pv cache limit is going to be exceeded"
341 " - pkg memory may get filled with pv declarations\n");
342 } else {
343 if(cfg_get(core, core_cfg, pv_cache_action)==1) {
344 pv_cache_drop();
345 }
346 }
347 }
348 pvid = get_hash1_raw(name->s, name->len);
349 pvn = (pv_cache_t*)pkg_malloc(sizeof(pv_cache_t) + name->len + 1);
350 if(pvn==0)
351 {
352 PKG_MEM_ERROR;
353 return NULL;
354 }
355 memset(pvn, 0, sizeof(pv_cache_t) + name->len + 1);
356 pvn->pvname.len = name->len;
357 pvn->pvname.s = (char*)pvn + sizeof(pv_cache_t);
358 memcpy(pvn->pvname.s, name->s, name->len);
359 p = pv_parse_spec(&pvn->pvname, &pvn->spec);
360
361 if(p==NULL)
362 {
363 pkg_free(pvn);
364 return NULL;
365 }
366 pvn->pvid = pvid;
367 pvn->next = _pv_cache[pvid%PV_CACHE_SIZE];
368 _pv_cache[pvid%PV_CACHE_SIZE] = pvn;
369 _pv_cache_counter++;
370
371 LM_DBG("pvar [%.*s] added in cache\n", name->len, name->s);
372 return &pvn->spec;
373 }
374
375 /**
376 *
377 */
pv_cache_lookup(str * name)378 pv_spec_t* pv_cache_lookup(str *name)
379 {
380 pv_cache_t *pvi;
381 unsigned int pvid;
382 int found;
383
384 if(_pv_cache_set==0)
385 return NULL;
386
387 pvid = get_hash1_raw(name->s, name->len);
388 pvi = _pv_cache[pvid%PV_CACHE_SIZE];
389 while(pvi)
390 {
391 if(pvi->pvid == pvid) {
392 if(pvi->pvname.len==name->len)
393 {
394 found = strncmp(pvi->pvname.s, name->s, name->len);
395
396 if(found==0)
397 {
398 LM_DBG("pvar [%.*s] found in cache\n",
399 name->len, name->s);
400 return &pvi->spec;
401 }
402 }
403 }
404 pvi = pvi->next;
405 }
406 return NULL;
407 }
408
409 /**
410 *
411 */
pv_cache_get(str * name)412 pv_spec_t* pv_cache_get(str *name)
413 {
414 pv_spec_t *pvs;
415 str tname;
416
417 if(name->s==NULL || name->len==0)
418 {
419 LM_ERR("invalid parameters\n");
420 return NULL;
421 }
422
423 tname.s = name->s;
424 tname.len = pv_locate_name(name);
425
426 if(tname.len < 0)
427 return NULL;
428
429 pvs = pv_cache_lookup(&tname);
430
431 if(pvs!=NULL)
432 return pvs;
433
434 return pv_cache_add(&tname);
435 }
436
pv_cache_get_name(pv_spec_t * spec)437 str* pv_cache_get_name(pv_spec_t *spec)
438 {
439 int i;
440 pv_cache_t *pvi;
441 if(spec==NULL)
442 {
443 LM_ERR("invalid parameters\n");
444 return NULL;
445 }
446
447 if(_pv_cache_set==0)
448 return NULL;
449
450 for(i=0;i<PV_CACHE_SIZE;i++)
451 {
452 pvi = _pv_cache[i];
453 while(pvi)
454 {
455 if(&pvi->spec == spec)
456 {
457 LM_DBG("pvar[%p]->name[%.*s] found in cache\n", spec,
458 pvi->pvname.len, pvi->pvname.s);
459 return &pvi->pvname;
460 }
461 pvi = pvi->next;
462 }
463 }
464 return NULL;
465 }
466
467 /**
468 *
469 */
pv_spec_lookup(str * name,int * len)470 pv_spec_t* pv_spec_lookup(str *name, int *len)
471 {
472 pv_spec_t *pvs;
473 str tname;
474
475 if(len!=NULL)
476 *len = 0;
477 if(name->s==NULL || name->len==0)
478 {
479 LM_ERR("invalid parameters\n");
480 return NULL;
481 }
482
483 tname.s = name->s;
484 tname.len = pv_locate_name(name);
485
486 if(tname.len < 0)
487 return NULL;
488
489 if(len!=NULL)
490 *len = tname.len;
491
492 pvs = pv_cache_lookup(&tname);
493
494 if(pvs!=NULL)
495 return pvs;
496
497 LM_DBG("PV <%.*s> is not in cache\n", tname.len, tname.s);
498 return pv_cache_add(&tname);
499 }
500
501 /**
502 *
503 */
register_pvars_mod(char * mod_name,pv_export_t * items)504 int register_pvars_mod(char *mod_name, pv_export_t *items)
505 {
506 int ret;
507 int i;
508
509 if (items==0)
510 return 0;
511
512 for ( i=0 ; items[i].name.s ; i++ ) {
513 ret = pv_table_add(&items[i]);
514 if (ret!=0) {
515 LM_ERR("failed to register pseudo-variable <%.*s> for module %s\n",
516 items[i].name.len, items[i].name.s, mod_name);
517 }
518 }
519 return 0;
520 }
521
522 /**
523 *
524 */
pv_table_free(void)525 int pv_table_free(void)
526 {
527 pv_item_p xe;
528 pv_item_p xe1;
529 int i;
530
531 for(i=0; i<PV_TABLE_SIZE; i++)
532 {
533 xe = _pv_table[i];
534 while(xe!=0)
535 {
536 xe1 = xe;
537 xe = xe->next;
538 pkg_free(xe1);
539 }
540 }
541 memset(_pv_table, 0, sizeof(pv_item_t*)*PV_TABLE_SIZE);
542 _pv_table_set = 0;
543
544 return 0;
545 }
546
547 /********** helper functions ********/
548 /**
549 * convert unsigned int to pv_value_t
550 */
pv_get_uintval(struct sip_msg * msg,pv_param_t * param,pv_value_t * res,unsigned int uival)551 int pv_get_uintval(struct sip_msg *msg, pv_param_t *param,
552 pv_value_t *res, unsigned int uival)
553 {
554 int l = 0;
555 char *ch = NULL;
556
557 if(res==NULL)
558 return -1;
559
560 ch = int2str(uival, &l);
561 res->rs.s = ch;
562 res->rs.len = l;
563
564 res->ri = (int)uival;
565 res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
566 return 0;
567 }
568
569 /**
570 * convert signed int to pv_value_t
571 */
pv_get_sintval(struct sip_msg * msg,pv_param_t * param,pv_value_t * res,int sival)572 int pv_get_sintval(struct sip_msg *msg, pv_param_t *param,
573 pv_value_t *res, int sival)
574 {
575 int l = 0;
576 char *ch = NULL;
577
578 if(res==NULL)
579 return -1;
580
581 ch = sint2str(sival, &l);
582 res->rs.s = ch;
583 res->rs.len = l;
584
585 res->ri = sival;
586 res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
587 return 0;
588 }
589
590 /**
591 * convert str to pv_value_t
592 */
pv_get_strval(struct sip_msg * msg,pv_param_t * param,pv_value_t * res,str * sval)593 int pv_get_strval(struct sip_msg *msg, pv_param_t *param,
594 pv_value_t *res, str *sval)
595 {
596 if(res==NULL)
597 return -1;
598
599 res->rs = *sval;
600 res->flags = PV_VAL_STR;
601 return 0;
602 }
603
604 /**
605 * convert strz to pv_value_t
606 */
pv_get_strzval(struct sip_msg * msg,pv_param_t * param,pv_value_t * res,char * sval)607 int pv_get_strzval(struct sip_msg *msg, pv_param_t *param,
608 pv_value_t *res, char *sval)
609 {
610 if(res==NULL)
611 return -1;
612
613 res->rs.s = sval;
614 res->rs.len = strlen(sval);
615 res->flags = PV_VAL_STR;
616 return 0;
617 }
618
619 /**
620 * convert char* with len to pv_value_t
621 */
pv_get_strlval(struct sip_msg * msg,pv_param_t * param,pv_value_t * res,char * sval,int slen)622 int pv_get_strlval(struct sip_msg *msg, pv_param_t *param,
623 pv_value_t *res, char *sval, int slen)
624 {
625 if(res==NULL)
626 return -1;
627
628 res->rs.s = sval;
629 res->rs.len = slen;
630 res->flags = PV_VAL_STR;
631 return 0;
632 }
633
634 /**
635 * convert str-int to pv_value_t (type is str)
636 */
pv_get_strintval(struct sip_msg * msg,pv_param_t * param,pv_value_t * res,str * sval,int ival)637 int pv_get_strintval(struct sip_msg *msg, pv_param_t *param,
638 pv_value_t *res, str *sval, int ival)
639 {
640 if(res==NULL)
641 return -1;
642
643 res->rs = *sval;
644 res->ri = ival;
645 res->flags = PV_VAL_STR|PV_VAL_INT;
646 return 0;
647 }
648
649 /**
650 * convert int-str to pv_value_t (type is int)
651 */
pv_get_intstrval(struct sip_msg * msg,pv_param_t * param,pv_value_t * res,int ival,str * sval)652 int pv_get_intstrval(struct sip_msg *msg, pv_param_t *param,
653 pv_value_t *res, int ival, str *sval)
654 {
655 if(res==NULL)
656 return -1;
657
658 res->rs = *sval;
659 res->ri = ival;
660 res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
661 return 0;
662 }
663
664 /*** ============================= ***/
665 static str pv_str_marker = { PV_MARKER_STR, 1 };
pv_get_marker(struct sip_msg * msg,pv_param_t * param,pv_value_t * res)666 static int pv_get_marker(struct sip_msg *msg, pv_param_t *param,
667 pv_value_t *res)
668 {
669 return pv_get_strintval(msg, param, res, &pv_str_marker,
670 (int)pv_str_marker.s[0]);
671 }
672
673 static char pv_str_empty_buf[2];
674 static char pv_str_null_buf[8];
675
676 static str pv_str_empty = { "", 0 };
677 #define PV_STR_NULL_VAL "<null>"
678 static str pv_str_null = { PV_STR_NULL_VAL, sizeof(PV_STR_NULL_VAL)-1 };
pv_get_null(struct sip_msg * msg,pv_param_t * param,pv_value_t * res)679 int pv_get_null(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
680 {
681 if(res==NULL)
682 return -1;
683
684 res->rs = pv_str_empty;
685 res->ri = 0;
686 res->flags = PV_VAL_NULL;
687 return 0;
688 }
689
690 /**
691 *
692 */
pv_get_null_str(void)693 str *pv_get_null_str(void)
694 {
695 return &pv_str_null;
696 }
697
698 /**
699 *
700 */
pv_get_empty_str(void)701 str *pv_get_empty_str(void)
702 {
703 return &pv_str_empty;
704 }
705
706 /**
707 *
708 */
pv_get_strempty(struct sip_msg * msg,pv_param_t * param,pv_value_t * res)709 int pv_get_strempty(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
710 {
711 if(res==NULL)
712 return -1;
713
714 res->rs = pv_str_empty;
715 res->ri = 0;
716 res->flags = PV_VAL_STR;
717 return 0;
718 }
719
720
721 /**
722 *
723 */
pv_lookup_spec_name(str * pvname,pv_spec_p e)724 pv_export_t* pv_lookup_spec_name(str *pvname, pv_spec_p e)
725 {
726 pv_item_t *pvi;
727 unsigned int pvid;
728
729 if(pvname==0 || e==0)
730 {
731 LM_ERR("bad parameters\n");
732 return NULL;
733 }
734
735 /* search in PV table */
736 // pvid = get_hash1_raw(pvname->s, pvname->len);
737 pvid = get_hash1_raw(pvname->s, pvname->len);
738 pvi = _pv_table[pvid%PV_TABLE_SIZE];
739 while(pvi)
740 {
741 if(pvi->pvid > pvid)
742 break;
743
744 if(pvi->pvid==pvid && pvi->pve.name.len==pvname->len
745 && memcmp(pvi->pve.name.s, pvname->s, pvname->len)==0)
746 {
747 /*LM_DBG("found [%.*s] [%d]\n", pvname->len, pvname->s,
748 _pv_names_table[i].type);*/
749 /* copy data from table to spec */
750 e->type = pvi->pve.type;
751 e->getf = pvi->pve.getf;
752 e->setf = pvi->pve.setf;
753 return &(pvi->pve);
754 }
755 pvi = pvi->next;
756 }
757
758 return NULL;
759 }
760
761 /**
762 *
763 */
pv_parse_index(pv_spec_p sp,str * in)764 int pv_parse_index(pv_spec_p sp, str *in)
765 {
766 char *p;
767 char *s;
768 int sign;
769 pv_spec_p nsp = 0;
770
771 if(in==NULL || in->s==NULL || sp==NULL)
772 return -1;
773 p = in->s;
774 if(*p==PV_MARKER)
775 {
776 nsp = (pv_spec_p)pkg_malloc(sizeof(pv_spec_t));
777 if(nsp==NULL)
778 {
779 PKG_MEM_ERROR;
780 return -1;
781 }
782 s = pv_parse_spec(in, nsp);
783 if(s==NULL)
784 {
785 LM_ERR("invalid index [%.*s]\n", in->len, in->s);
786 pv_spec_free(nsp);
787 return -1;
788 }
789 sp->pvp.pvi.type = PV_IDX_PVAR;
790 sp->pvp.pvi.u.dval = (void*)nsp;
791 return 0;
792 }
793 if(*p=='*' && in->len==1)
794 {
795 sp->pvp.pvi.type = PV_IDX_ALL;
796 return 0;
797 }
798 if(*p=='+' && in->len==1)
799 {
800 sp->pvp.pvi.type = PV_IDX_ITR;
801 return 0;
802 }
803 sign = 1;
804 if(*p=='-')
805 {
806 sign = -1;
807 p++;
808 }
809 sp->pvp.pvi.u.ival = 0;
810 while(p<in->s+in->len && *p>='0' && *p<='9')
811 {
812 sp->pvp.pvi.u.ival = sp->pvp.pvi.u.ival * 10 + *p - '0';
813 p++;
814 }
815 if(p!=in->s+in->len)
816 {
817 LM_ERR("invalid index [%.*s]\n", in->len, in->s);
818 return -1;
819 }
820 sp->pvp.pvi.u.ival *= sign;
821 sp->pvp.pvi.type = PV_IDX_INT;
822 return 0;
823 }
824
825 /**
826 *
827 */
pv_init_iname(pv_spec_p sp,int param)828 int pv_init_iname(pv_spec_p sp, int param)
829 {
830 if(sp==NULL)
831 return -1;
832 sp->pvp.pvn.type = PV_NAME_INTSTR;
833 sp->pvp.pvn.u.isname.name.n = param;
834 return 0;
835 }
836
837 /**
838 *
839 */
pv_parse_spec2(str * in,pv_spec_p e,int silent)840 char* pv_parse_spec2(str *in, pv_spec_p e, int silent)
841 {
842 char *p;
843 str s;
844 str pvname;
845 int pvstate;
846 trans_t *tr = NULL;
847 pv_export_t *pte = NULL;
848 int n=0;
849
850 if(in==NULL || in->s==NULL || e==NULL || *in->s!=PV_MARKER)
851 {
852 if (!silent) LM_ERR("bad parameters\n");
853 return NULL;
854 }
855
856 /* LM_DBG("***** input [%.*s] (%d)\n", in->len, in->s, in->len); */
857 tr = 0;
858 pvstate = 0;
859 memset(e, 0, sizeof(pv_spec_t));
860 e->pvp.pvi.type = PV_IDX_NONE;
861 p = in->s;
862 p++;
863 if(*p==PV_LNBRACKET)
864 {
865 p++;
866 pvstate = 1;
867 }
868 pvname.s = p;
869 if(*p == PV_MARKER) {
870 p++;
871 if(pvstate==1)
872 {
873 if(*p!=PV_RNBRACKET)
874 goto error;
875 p++;
876 }
877 e->getf = pv_get_marker;
878 e->type = PVT_MARKER;
879 pvname.len = 1;
880 goto done_all;
881 }
882 while(is_in_str(p,in) && is_pv_valid_char(*p))
883 p++;
884 pvname.len = p - pvname.s;
885 if(pvstate==1)
886 {
887 if(*p==PV_RNBRACKET)
888 { /* full pv name ended here*/
889 goto done_inm;
890 } else if(*p==PV_LNBRACKET) {
891 p++;
892 pvstate = 2;
893 } else if(*p==PV_LIBRACKET) {
894 p++;
895 pvstate = 3;
896 } else if(*p==TR_LBRACKET) {
897 p++;
898 pvstate = 4;
899 } else {
900 if (!silent)
901 LM_ERR("invalid char '%c' in [%.*s] (%d)\n",
902 *p, in->len, in->s, pvstate);
903 goto error;
904 }
905 } else {
906 if(!is_in_str(p, in)) {
907 p--;
908 goto done_inm;
909 } else if(*p==PV_LNBRACKET) {
910 p++;
911 pvstate = 5;
912 } else {
913 /* still in input str, but end of PV */
914 /* p is increased at the end, so decrement here */
915 p--;
916 goto done_inm;
917 }
918 }
919
920 done_inm:
921 if((pte = pv_lookup_spec_name(&pvname, e))==NULL)
922 {
923 if (!silent)
924 LM_ERR("error searching pvar \"%.*s\"\n", pvname.len, pvname.s);
925 goto error;
926 }
927 if(pte->parse_name!=NULL && pvstate!=2 && pvstate!=5)
928 {
929 if (!silent)
930 LM_ERR("pvar \"%.*s\" expects an inner name\n",
931 pvname.len, pvname.s);
932 goto error;
933 }
934 if(pvstate==2 || pvstate==5)
935 {
936 if(pte->parse_name==NULL)
937 {
938 if (!silent)
939 LM_ERR("pvar \"%.*s\" does not get name param\n",
940 pvname.len, pvname.s);
941 goto error;
942 }
943 s.s = p;
944 n = 0;
945 while(is_in_str(p, in))
946 {
947 if(*p==PV_RNBRACKET)
948 {
949 if(n==0)
950 break;
951 n--;
952 }
953 if(*p == PV_LNBRACKET)
954 n++;
955 p++;
956 }
957
958 if(!is_in_str(p, in))
959 goto error;
960
961 if(p==s.s)
962 {
963 if (!silent)
964 LM_ERR("pvar \"%.*s\" does not get empty name param\n",
965 pvname.len, pvname.s);
966 goto error;
967 }
968 s.len = p - s.s;
969 if(pte->parse_name(e, &s)!=0)
970 {
971 if (!silent)
972 LM_ERR("pvar \"%.*s\" has an invalid name param [%.*s]\n",
973 pvname.len, pvname.s, s.len, s.s);
974 goto error;
975 }
976 if(pvstate==2)
977 {
978 p++;
979 if(*p==PV_RNBRACKET)
980 { /* full pv name ended here*/
981 goto done_vnm;
982 } else if(*p==PV_LIBRACKET) {
983 p++;
984 pvstate = 3;
985 } else if(*p==TR_LBRACKET) {
986 p++;
987 pvstate = 4;
988 } else {
989 if (!silent)
990 LM_ERR("invalid char '%c' in [%.*s] (%d)\n",
991 *p, in->len, in->s, pvstate);
992 goto error;
993 }
994 } else {
995 if(*p==PV_RNBRACKET)
996 { /* full pv name ended here*/
997 p++;
998 goto done_all;
999 } else {
1000 if (!silent)
1001 LM_ERR("invalid char '%c' in [%.*s] (%d)\n",
1002 *p, in->len, in->s, pvstate);
1003 goto error;
1004 }
1005 }
1006 }
1007 done_vnm:
1008 if(pvstate==3)
1009 {
1010 if(pte->parse_index==NULL)
1011 {
1012 if (!silent)
1013 LM_ERR("pvar \"%.*s\" does not get index param\n",
1014 pvname.len, pvname.s);
1015 goto error;
1016 }
1017 s.s = p;
1018 n = 0;
1019 while(is_in_str(p, in))
1020 {
1021 if(*p==PV_RIBRACKET)
1022 {
1023 if(n==0)
1024 break;
1025 n--;
1026 }
1027 if(*p == PV_LIBRACKET)
1028 n++;
1029 p++;
1030 }
1031 if(!is_in_str(p, in))
1032 goto error;
1033
1034 if(p==s.s)
1035 {
1036 if (!silent)
1037 LM_ERR("pvar \"%.*s\" does not get empty index param\n",
1038 pvname.len, pvname.s);
1039 goto error;
1040 }
1041 s.len = p - s.s;
1042 if(pte->parse_index(e, &s)!=0)
1043 {
1044 if (!silent)
1045 LM_ERR("pvar \"%.*s\" has an invalid index param [%.*s]\n",
1046 pvname.len, pvname.s, s.len, s.s);
1047 goto error;
1048 }
1049 p++;
1050 if(*p==PV_RNBRACKET)
1051 { /* full pv name ended here*/
1052 goto done_idx;
1053 } else if(*p==TR_LBRACKET) {
1054 p++;
1055 pvstate = 4;
1056 } else {
1057 if (!silent)
1058 LM_ERR("invalid char '%c' in [%.*s] (%d)\n",
1059 *p, in->len, in->s, pvstate);
1060 goto error;
1061 }
1062 }
1063 done_idx:
1064 if(pvstate==4)
1065 {
1066 s.s = p-1;
1067 n = 0;
1068 while(is_in_str(p, in))
1069 {
1070 if(*p==TR_RBRACKET)
1071 {
1072 if(n==0)
1073 {
1074 /* yet another transformation */
1075 p++;
1076 while(is_in_str(p, in) && (*p==' ' || *p=='\t')) p++;
1077
1078 if(!is_in_str(p, in) || *p != TR_LBRACKET)
1079 {
1080 p--;
1081 break;
1082 }
1083 }
1084 n--;
1085 }
1086 if(*p == TR_LBRACKET)
1087 n++;
1088 p++;
1089 }
1090 if(!is_in_str(p, in))
1091 goto error;
1092
1093 if(p==s.s)
1094 {
1095 if (!silent)
1096 LM_ERR("pvar \"%.*s\" does not get empty index param\n",
1097 pvname.len, pvname.s);
1098 goto error;
1099 }
1100 s.len = p - s.s + 1;
1101
1102 p = tr_lookup(&s, &tr);
1103 if(p==NULL)
1104 {
1105 if (!silent)
1106 LM_ERR("bad tr in pvar name \"%.*s\"\n", pvname.len, pvname.s);
1107 goto error;
1108 }
1109 if(*p!=PV_RNBRACKET)
1110 {
1111 if (!silent)
1112 LM_ERR("bad pvar name \"%.*s\" (%c)!\n", in->len, in->s, *p);
1113 goto error;
1114 }
1115 e->trans = (void*)tr;
1116 }
1117 p++;
1118
1119 done_all:
1120 if(pte!=NULL && pte->init_param)
1121 pte->init_param(e, pte->iparam);
1122 return p;
1123
1124 error:
1125 if(p!=NULL){
1126 if (!silent)
1127 LM_ERR("wrong char [%c/%d] in [%.*s] at [%d (%d)]\n", *p, (int)*p,
1128 in->len, in->s, (int)(p-in->s), pvstate);
1129 }else{
1130 if (!silent)
1131 LM_ERR("invalid parsing in [%.*s] at (%d)\n",
1132 in->len, in->s, pvstate);
1133 }
1134 return NULL;
1135
1136 } /* end: pv_parse_spec */
1137
1138 /**
1139 *
1140 */
pv_parse_format(str * in,pv_elem_p * el)1141 int pv_parse_format(str *in, pv_elem_p *el)
1142 {
1143 char *p, *p0;
1144 int n = 0;
1145 pv_elem_p e, e0;
1146 str s;
1147 int len;
1148
1149 if(in==NULL || in->s==NULL || el==NULL)
1150 return -1;
1151
1152 /*LM_DBG("parsing [%.*s]\n", in->len, in->s);*/
1153
1154 if(in->len == 0)
1155 {
1156 *el = pkg_malloc(sizeof(pv_elem_t));
1157 if(*el == NULL) {
1158 PKG_MEM_ERROR;
1159 goto error;
1160 }
1161 memset(*el, 0, sizeof(pv_elem_t));
1162 (*el)->text = *in;
1163 return 0;
1164 }
1165
1166 p = in->s;
1167 *el = NULL;
1168 e = e0 = NULL;
1169
1170 while(is_in_str(p,in))
1171 {
1172 e0 = e;
1173 e = pkg_malloc(sizeof(pv_elem_t));
1174 if(!e) {
1175 PKG_MEM_ERROR;
1176 goto error;
1177 }
1178 memset(e, 0, sizeof(pv_elem_t));
1179 n++;
1180 if(*el == NULL)
1181 *el = e;
1182 if(e0)
1183 e0->next = e;
1184
1185 e->text.s = p;
1186 while(is_in_str(p,in) && *p!=PV_MARKER)
1187 p++;
1188 e->text.len = p - e->text.s;
1189
1190 if(*p == '\0' || !is_in_str(p,in))
1191 break;
1192 s.s = p;
1193 s.len = in->s+in->len-p;
1194 e->spec = pv_spec_lookup(&s, &len);
1195 if(e->spec==NULL)
1196 goto error;
1197 p0 = p + len;
1198
1199 if(*p0 == '\0')
1200 break;
1201 p = p0;
1202 }
1203 /*LM_DBG("format parsed OK: [%d] items\n", n);*/
1204
1205 if(*el == NULL)
1206 return -1;
1207
1208 return 0;
1209
1210 error:
1211 pv_elem_free_all(*el);
1212 *el = NULL;
1213 return -1;
1214 }
1215
1216 /**
1217 *
1218 */
pv_get_spec_name(struct sip_msg * msg,pv_param_p ip,pv_value_t * name)1219 int pv_get_spec_name(struct sip_msg* msg, pv_param_p ip, pv_value_t *name)
1220 {
1221 if(msg==NULL || ip==NULL || name==NULL)
1222 return -1;
1223 memset(name, 0, sizeof(pv_value_t));
1224
1225 if(ip->pvn.type==PV_NAME_INTSTR)
1226 {
1227 if(ip->pvn.u.isname.type&AVP_NAME_STR)
1228 {
1229 name->rs = ip->pvn.u.isname.name.s;
1230 name->flags = PV_VAL_STR;
1231 } else {
1232 name->ri = ip->pvn.u.isname.name.n;
1233 name->flags = PV_VAL_INT|PV_TYPE_INT;
1234 }
1235 return 0;
1236 } else if(ip->pvn.type==PV_NAME_PVAR) {
1237 /* pvar */
1238 if(pv_get_spec_value(msg, (pv_spec_p)(ip->pvn.u.dname), name)!=0)
1239 {
1240 LM_ERR("cannot get name value\n");
1241 return -1;
1242 }
1243 if(name->flags&PV_VAL_NULL || name->flags&PV_VAL_EMPTY)
1244 {
1245 LM_ERR("null or empty name\n");
1246 return -1;
1247 }
1248 return 0;
1249 }
1250 LM_ERR("name type is PV_NAME_OTHER - cannot resolve\n");
1251 return -1;
1252 }
1253
1254 /**
1255 * parse AVP name
1256 * @return 0 on success, -1 on error
1257 */
pv_parse_avp_name(pv_spec_p sp,str * in)1258 int pv_parse_avp_name(pv_spec_p sp, str *in)
1259 {
1260 char *p;
1261 char *s;
1262 pv_spec_p nsp = 0;
1263
1264 if(in==NULL || in->s==NULL || sp==NULL)
1265 return -1;
1266 p = in->s;
1267 if(*p==PV_MARKER)
1268 {
1269 nsp = (pv_spec_p)pkg_malloc(sizeof(pv_spec_t));
1270 if(nsp==NULL)
1271 {
1272 PKG_MEM_ERROR;
1273 return -1;
1274 }
1275 s = pv_parse_spec(in, nsp);
1276 if(s==NULL)
1277 {
1278 LM_ERR("invalid name [%.*s]\n", in->len, in->s);
1279 pv_spec_free(nsp);
1280 return -1;
1281 }
1282 //LM_ERR("dynamic name [%.*s]\n", in->len, in->s);
1283 //pv_print_spec(nsp);
1284 sp->pvp.pvn.type = PV_NAME_PVAR;
1285 sp->pvp.pvn.u.dname = (void*)nsp;
1286 return 0;
1287 }
1288 /*LM_DBG("static name [%.*s]\n", in->len, in->s);*/
1289 if(km_parse_avp_spec(in, &sp->pvp.pvn.u.isname.type,
1290 &sp->pvp.pvn.u.isname.name)!=0)
1291 {
1292 LM_ERR("bad avp name [%.*s]\n", in->len, in->s);
1293 return -1;
1294 }
1295 sp->pvp.pvn.type = PV_NAME_INTSTR;
1296 return 0;
1297 }
1298
1299 /**
1300 * fill avp name details (id and type)
1301 * @return 0 on success, -1 on error
1302 */
pv_get_avp_name(struct sip_msg * msg,pv_param_p ip,int_str * avp_name,unsigned short * name_type)1303 int pv_get_avp_name(struct sip_msg* msg, pv_param_p ip, int_str *avp_name,
1304 unsigned short *name_type)
1305 {
1306 pv_value_t tv;
1307 if(ip==NULL || avp_name==NULL || name_type==NULL)
1308 return -1;
1309 memset(avp_name, 0, sizeof(int_str));
1310 *name_type = 0;
1311
1312 if(ip->pvn.type==PV_NAME_INTSTR)
1313 {
1314 *name_type = ip->pvn.u.isname.type;
1315 if(ip->pvn.u.isname.type&AVP_NAME_STR)
1316 {
1317 avp_name->s = ip->pvn.u.isname.name.s;
1318 *name_type |= AVP_NAME_STR;
1319 } else {
1320 avp_name->n = ip->pvn.u.isname.name.n;
1321 /* *name_type &= AVP_SCRIPT_MASK; */
1322 *name_type = 0;
1323 }
1324 return 0;
1325 }
1326 /* pvar */
1327 if(pv_get_spec_value(msg, (pv_spec_p)(ip->pvn.u.dname), &tv)!=0)
1328 {
1329 LM_ERR("cannot get avp value\n");
1330 return -1;
1331 }
1332 if(tv.flags&PV_VAL_NULL || tv.flags&PV_VAL_EMPTY)
1333 {
1334 LM_ERR("null or empty name\n");
1335 return -1;
1336 }
1337
1338 if((tv.flags&PV_TYPE_INT) && (tv.flags&PV_VAL_INT))
1339 {
1340 avp_name->n = tv.ri;
1341 } else {
1342 avp_name->s = tv.rs;
1343 *name_type = AVP_NAME_STR;
1344 }
1345 return 0;
1346 }
1347
1348 /**
1349 *
1350 */
pv_get_spec_index(struct sip_msg * msg,pv_param_p ip,int * idx,int * flags)1351 int pv_get_spec_index(struct sip_msg* msg, pv_param_p ip, int *idx, int *flags)
1352 {
1353 pv_value_t tv;
1354 if(ip==NULL || idx==NULL || flags==NULL)
1355 return -1;
1356
1357 *idx = 0;
1358 *flags = 0;
1359
1360 if(ip->pvi.type == PV_IDX_ALL) {
1361 *flags = PV_IDX_ALL;
1362 return 0;
1363 }
1364 if(ip->pvi.type == PV_IDX_ITR) {
1365 *flags = PV_IDX_ITR;
1366 return 0;
1367 }
1368 if(ip->pvi.type == PV_IDX_INT)
1369 {
1370 *idx = ip->pvi.u.ival;
1371 return 0;
1372 }
1373 if(ip->pvi.type == PV_IDX_NONE)
1374 {
1375 *flags = PV_IDX_NONE;
1376 *idx = ip->pvi.u.ival;
1377 return 0;
1378 }
1379
1380 /* pvar */
1381 if(pv_get_spec_value(msg, (pv_spec_p)ip->pvi.u.dval, &tv)!=0)
1382 {
1383 LM_ERR("cannot get index value\n");
1384 return -1;
1385 }
1386 if(!(tv.flags&PV_VAL_INT))
1387 {
1388 LM_ERR("invalid index value\n");
1389 return -1;
1390 }
1391 *idx = tv.ri;
1392 return 0;
1393 }
1394
1395 /**
1396 *
1397 */
pv_get_spec_value(struct sip_msg * msg,pv_spec_p sp,pv_value_t * value)1398 int pv_get_spec_value(struct sip_msg* msg, pv_spec_p sp, pv_value_t *value)
1399 {
1400 int ret = 0;
1401
1402 if(msg==NULL || sp==NULL || sp->getf==NULL || value==NULL
1403 || sp->type==PVT_NONE)
1404 {
1405 LM_ERR("bad parameters\n");
1406 return -1;
1407 }
1408
1409 memset(value, 0, sizeof(pv_value_t));
1410
1411 ret = (*sp->getf)(msg, &(sp->pvp), value);
1412 if(ret!=0)
1413 return ret;
1414
1415 if(sp->trans)
1416 return tr_exec(msg, (trans_t*)sp->trans, value);
1417 return ret;
1418 }
1419
1420 /**
1421 *
1422 */
pv_set_spec_value(struct sip_msg * msg,pv_spec_p sp,int op,pv_value_t * value)1423 int pv_set_spec_value(struct sip_msg* msg, pv_spec_p sp, int op,
1424 pv_value_t *value)
1425 {
1426 if(sp==NULL || !pv_is_w(sp))
1427 return 0; /* no op */
1428 if(pv_alter_context(sp) && is_route_type(LOCAL_ROUTE))
1429 return 0; /* no op */
1430 return sp->setf(msg, &sp->pvp, op, value);
1431 }
1432
1433 /**
1434 *
1435 */
pv_printf_mode(sip_msg_t * msg,pv_elem_t * list,int mode,char * buf,int * len)1436 int pv_printf_mode(sip_msg_t* msg, pv_elem_t *list, int mode, char *buf, int *len)
1437 {
1438 int n;
1439 pv_value_t tok;
1440 pv_elem_p it;
1441 char *cur;
1442
1443 if(msg==NULL || list==NULL || buf==NULL || len==NULL) {
1444 LM_DBG("invalid parameters\n");
1445 return -1;
1446 }
1447
1448 if(*len <= 0) {
1449 LM_DBG("invalid value for output buffer size\n");
1450 return -1;
1451 }
1452
1453 *buf = '\0';
1454 cur = buf;
1455
1456 n = 0;
1457 for (it=list; it; it=it->next)
1458 {
1459 /* put the text */
1460 if(it->text.s && it->text.len>0)
1461 {
1462 if(n+it->text.len < *len)
1463 {
1464 memcpy(cur, it->text.s, it->text.len);
1465 n += it->text.len;
1466 cur += it->text.len;
1467 } else {
1468 if(likely(mode)) {
1469 LM_ERR("no more space for text value - printed:%d token:%d buffer:%d\n",
1470 n, it->text.len, *len);
1471 }
1472 goto overflow;
1473 }
1474 }
1475 /* put the value of the specifier */
1476 if(it->spec!=NULL && it->spec->type!=PVT_NONE
1477 && pv_get_spec_value(msg, it->spec, &tok)==0)
1478 {
1479 if(tok.flags&PV_VAL_NULL)
1480 tok.rs = pv_str_null;
1481 if(n+tok.rs.len < *len)
1482 {
1483 if(tok.rs.len>0)
1484 {
1485 memcpy(cur, tok.rs.s, tok.rs.len);
1486 n += tok.rs.len;
1487 cur += tok.rs.len;
1488 }
1489 } else {
1490 if(likely(mode)) {
1491 LM_ERR("no more space for spec value - printed:%d token:%d buffer:%d\n",
1492 n, tok.rs.len, *len);
1493 }
1494 goto overflow;
1495 }
1496 }
1497 }
1498
1499 goto done;
1500
1501 overflow:
1502 if(likely(mode)) {
1503 LM_ERR("buffer overflow -- increase the buffer size...\n");
1504 }
1505 return -2;
1506
1507 done:
1508 #ifdef EXTRA_DEBUG
1509 LM_DBG("final buffer length %d\n", n);
1510 #endif
1511 *cur = '\0';
1512 *len = n;
1513 return 0;
1514 }
1515
1516 /**
1517 *
1518 */
pv_printf(sip_msg_t * msg,pv_elem_t * list,char * buf,int * len)1519 int pv_printf(sip_msg_t* msg, pv_elem_t *list, char *buf, int *len)
1520 {
1521 return pv_printf_mode(msg, list, 1, buf, len);
1522 }
1523
1524 /**
1525 *
1526 */
pv_printf_size(sip_msg_t * msg,pv_elem_t * list)1527 int pv_printf_size(sip_msg_t* msg, pv_elem_t *list)
1528 {
1529 int n;
1530 pv_value_t tok;
1531 pv_elem_t *it;
1532
1533 if(msg==NULL || list==NULL) {
1534 return -1;
1535 }
1536
1537 n = 0;
1538 for (it=list; it; it=it->next) {
1539 /* count the static text */
1540 if(it->text.s && it->text.len>0) {
1541 n += it->text.len;
1542 }
1543 /* count the value of the specifier */
1544 if(it->spec!=NULL && it->spec->type!=PVT_NONE
1545 && pv_get_spec_value(msg, it->spec, &tok)==0)
1546 {
1547 if(tok.flags&PV_VAL_NULL) {
1548 tok.rs = pv_str_null;
1549 }
1550 n += tok.rs.len;
1551 }
1552 }
1553
1554 return n;
1555 }
1556
1557 /**
1558 *
1559 */
parse_pvname_list(str * in,unsigned int type)1560 pvname_list_t* parse_pvname_list(str *in, unsigned int type)
1561 {
1562 pvname_list_t* head = NULL;
1563 pvname_list_t* al = NULL;
1564 pvname_list_t* last = NULL;
1565 char *p;
1566 pv_spec_t spec;
1567 str s;
1568
1569 if(in==NULL || in->s==NULL)
1570 {
1571 LM_ERR("bad parameters\n");
1572 return NULL;
1573 }
1574
1575 p = in->s;
1576 while(is_in_str(p, in))
1577 {
1578 while(is_in_str(p, in) && (*p==' '||*p=='\t'||*p==','||*p==';'||*p=='\n'))
1579 p++;
1580 if(!is_in_str(p, in))
1581 {
1582 if(head==NULL)
1583 LM_ERR("parse error in name list [%.*s]\n", in->len, in->s);
1584 return head;
1585 }
1586 s.s = p;
1587 s.len = in->s + in->len - p;
1588 p = pv_parse_spec(&s, &spec);
1589 if(p==NULL)
1590 {
1591 LM_ERR("parse error in item [%.*s]\n", s.len, s.s);
1592 goto error;
1593 }
1594 if(type && spec.type!=type)
1595 {
1596 LM_ERR("wrong type for item [%.*s]\n", (int)(p-s.s), s.s);
1597 goto error;
1598 }
1599 al = (pvname_list_t*)pkg_malloc(sizeof(pvname_list_t));
1600 if(al==NULL)
1601 {
1602 PKG_MEM_ERROR;
1603 goto error;
1604 }
1605 memset(al, 0, sizeof(pvname_list_t));
1606 memcpy(&al->sname, &spec, sizeof(pv_spec_t));
1607
1608 if(last==NULL)
1609 {
1610 head = al;
1611 last = al;
1612 } else {
1613 last->next = al;
1614 last = al;
1615 }
1616 }
1617
1618 return head;
1619
1620 error:
1621 while(head)
1622 {
1623 al = head;
1624 head=head->next;
1625 pkg_free(al);
1626 }
1627 return NULL;
1628 }
1629
1630 /**
1631 *
1632 */
free_pvname_list(pvname_list_t * head)1633 void free_pvname_list(pvname_list_t* head)
1634 {
1635 pvname_list_t* al;
1636
1637 while(head) {
1638 al = head;
1639 head=head->next;
1640 pkg_free(al);
1641 }
1642 }
1643
1644
1645 /** destroy the content of pv_spec_t structure.
1646 */
pv_spec_destroy(pv_spec_t * spec)1647 void pv_spec_destroy(pv_spec_t *spec)
1648 {
1649 if(spec==0) return;
1650 /* free name if it is PV */
1651 if(spec->pvp.pvn.nfree)
1652 spec->pvp.pvn.nfree((void*)(&spec->pvp.pvn));
1653 if(spec->trans)
1654 tr_free((trans_t*)spec->trans);
1655 }
1656
1657 /** free the pv_spec_t structure.
1658 */
pv_spec_free(pv_spec_t * spec)1659 void pv_spec_free(pv_spec_t *spec)
1660 {
1661 if(spec==0) return;
1662 pv_spec_destroy(spec);
1663 pkg_free(spec);
1664 }
1665
1666 /**
1667 *
1668 */
pv_elem_free_all(pv_elem_p log)1669 int pv_elem_free_all(pv_elem_p log)
1670 {
1671 pv_elem_p t;
1672 while(log)
1673 {
1674 t = log;
1675 log = log->next;
1676 pkg_free(t);
1677 }
1678 return 0;
1679 }
1680
1681 /**
1682 *
1683 */
pv_value_destroy(pv_value_t * val)1684 void pv_value_destroy(pv_value_t *val)
1685 {
1686 if(val==0) return;
1687
1688 if(val->flags&PV_VAL_PKG) pkg_free(val->rs.s);
1689 else if(val->flags&PV_VAL_SHM) shm_free(val->rs.s);
1690
1691 memset(val, 0, sizeof(pv_value_t));
1692 }
1693
pv_printf_s(struct sip_msg * msg,pv_elem_p list,str * s)1694 int pv_printf_s(struct sip_msg* msg, pv_elem_p list, str *s)
1695 {
1696 s->s = pv_get_buffer();
1697 s->len = pv_get_buffer_size();
1698 return pv_printf( msg, list, s->s, &s->len);
1699 }
1700
1701 /********************************************************
1702 * Transformations API
1703 ********************************************************/
1704
1705 /**
1706 *
1707 */
tr_get_class(str * in,char * p,str * tclass)1708 static inline char* tr_get_class(str *in, char *p, str *tclass)
1709 {
1710 tclass->s = p;
1711 while(is_in_str(p, in) && *p!=TR_CLASS_MARKER) p++;
1712 if(*p!=TR_CLASS_MARKER || tclass->s == p)
1713 {
1714 LM_ERR("invalid transformation: %.*s (%c)!\n", in->len, in->s, *p);
1715 return NULL;
1716 }
1717 tclass->len = p - tclass->s;
1718 p++;
1719
1720 return p;
1721 }
1722
1723 /**
1724 *
1725 */
tr_new(void)1726 static inline trans_t* tr_new(void)
1727 {
1728 trans_t *t = NULL;
1729
1730 t = (trans_t*)pkg_malloc(sizeof(trans_t));
1731 if(t == NULL)
1732 {
1733 PKG_MEM_ERROR;
1734 return NULL;
1735 }
1736 memset(t, 0, sizeof(trans_t));
1737 return t;
1738 }
1739
tr_lookup(str * in,trans_t ** tr)1740 char* tr_lookup(str *in, trans_t **tr)
1741 {
1742 char *p;
1743 char *p0;
1744 str tclass;
1745 tr_export_t *te = NULL;
1746 trans_t *t = NULL;
1747 trans_t *t0 = NULL;
1748 str s;
1749
1750 if(in==NULL || in->s==NULL || tr==NULL)
1751 return NULL;
1752
1753 p = in->s;
1754 do {
1755 while(is_in_str(p, in) && (*p==' ' || *p=='\t' || *p=='\n')) p++;
1756 if(*p != TR_LBRACKET)
1757 break;
1758 p++;
1759
1760 if((t = tr_new())==NULL) return NULL;
1761
1762 if(t0==NULL) *tr = t;
1763 else t0->next = t;
1764 t0 = t;
1765
1766 /* find transformation class */
1767 p = tr_get_class(in, p, &tclass);
1768 if(p==NULL) goto error;
1769
1770 /* locate transformation */
1771 te = tr_lookup_class(&tclass);
1772 if(te==NULL)
1773 {
1774 LM_ERR("unknown transformation: [%.*s] in [%.*s]\n",
1775 tclass.len, tclass.s, in->len, in->s);
1776 goto error;
1777 }
1778
1779 s.s = p; s.len = in->s + in->len - p;
1780 p0 = te->tparse(&s, t);
1781 if(p0==NULL)
1782 goto error;
1783 p = p0;
1784
1785 if(*p != TR_RBRACKET)
1786 {
1787 LM_ERR("invalid transformation: %.*s | %c !!\n", in->len,
1788 in->s, *p);
1789 goto error;
1790 }
1791
1792 p++;
1793 if(!is_in_str(p, in))
1794 break;
1795 } while(1);
1796
1797 return p;
1798 error:
1799 LM_ERR("error parsing [%.*s]\n", in->len, in->s);
1800 t = *tr;
1801 while(t)
1802 {
1803 t0 = t;
1804 t = t->next;
1805 tr_destroy(t0);
1806 pkg_free(t0);
1807 }
1808 return NULL;
1809 }
1810
1811 /*!
1812 * \brief Destroy transformation including eventual parameter
1813 * \param t transformation
1814 */
tr_destroy(trans_t * t)1815 void tr_destroy(trans_t *t)
1816 {
1817 tr_param_t *tp;
1818 tr_param_t *tp0;
1819 if(t==NULL) return;
1820
1821 tp = t->params;
1822 while(tp)
1823 {
1824 tp0 = tp;
1825 tp = tp->next;
1826 tr_param_free(tp0);
1827 }
1828 memset(t, 0, sizeof(trans_t));
1829 }
1830
1831 /*!
1832 * \brief Exec transformation on a pseudo-variable value
1833 * \param msg SIP message
1834 * \param t one or more transformations
1835 * \param v pseudo-variable value
1836 * \return 0 on success, -1 on error
1837 */
tr_exec(struct sip_msg * msg,trans_t * t,pv_value_t * v)1838 int tr_exec(struct sip_msg *msg, trans_t *t, pv_value_t *v)
1839 {
1840 int r;
1841 trans_t *i;
1842
1843 if(t==NULL || v==NULL)
1844 {
1845 LM_DBG("invalid parameters\n");
1846 return -1;
1847 }
1848
1849 for(i = t; i!=NULL; i=i->next)
1850 {
1851 r = (*i->trf)(msg, i->params, i->subtype, v);
1852 if(r!=0)
1853 return r;
1854 }
1855 return 0;
1856 }
1857
1858 /*!
1859 * \brief Free allocated memory of transformation list
1860 * \param t transformation list
1861 */
tr_free(trans_t * t)1862 void tr_free(trans_t *t)
1863 {
1864 trans_t *t0;
1865
1866 while(t)
1867 {
1868 t0 = t;
1869 t = t->next;
1870 tr_destroy(t0);
1871 pkg_free(t0);
1872 }
1873 }
1874
1875
1876 /*!
1877 * \brief Free transformation parameter list
1878 * \param tp transformation list
1879 */
tr_param_free(tr_param_t * tp)1880 void tr_param_free(tr_param_t *tp)
1881 {
1882 tr_param_t *tp0;
1883
1884 if(tp==NULL) return;
1885 while(tp)
1886 {
1887 tp0 = tp;
1888 tp = tp->next;
1889 if(tp0->type==TR_PARAM_SPEC)
1890 pv_spec_free((pv_spec_t*)tp0->v.data);
1891 pkg_free(tp0);
1892 }
1893 }
1894
1895 typedef struct _tr_item
1896 {
1897 tr_export_t tre;
1898 unsigned int trid;
1899 struct _tr_item *next;
1900 } tr_item_t, *tr_item_p;
1901
1902 static tr_item_t* _tr_table[TR_TABLE_SIZE];
1903 static int _tr_table_set = 0;
1904
1905
1906 /**
1907 *
1908 */
tr_init_table(void)1909 void tr_init_table(void)
1910 {
1911 memset(_tr_table, 0, sizeof(tr_item_t*)*TR_TABLE_SIZE);
1912 _tr_table_set = 1;
1913 }
1914
1915 /**
1916 *
1917 */
tr_table_add(tr_export_t * e)1918 int tr_table_add(tr_export_t *e)
1919 {
1920 tr_item_t *tri = NULL;
1921 tr_item_t *trj = NULL;
1922 tr_item_t *trn = NULL;
1923 int found;
1924 unsigned int trid;
1925
1926 if(e==NULL || e->tclass.s==NULL)
1927 {
1928 LM_ERR("invalid parameters\n");
1929 return -1;
1930 }
1931
1932 if(_tr_table_set==0)
1933 {
1934 LM_DBG("TR table not initialized, doing it now\n");
1935 tr_init_table();
1936 }
1937
1938 found = 0;
1939 // trid = get_hash1_raw(e->tclass.s, e->tclass.len);
1940 trid = get_hash1_raw(e->tclass.s, e->tclass.len);
1941
1942 tri = _tr_table[trid%TR_TABLE_SIZE];
1943 while(tri)
1944 {
1945 if(tri->tre.tclass.len==e->tclass.len)
1946 {
1947 found = strncmp(tri->tre.tclass.s, e->tclass.s, e->tclass.len);
1948 if(found==0)
1949 {
1950 LM_ERR("TR class [%.*s] already exists\n", e->tclass.len,
1951 e->tclass.s);
1952 return -1;
1953 }
1954 }
1955 trj = tri;
1956 tri = tri->next;
1957 }
1958
1959 trn = (tr_item_t*)pkg_malloc(sizeof(tr_item_t));
1960 if(trn==0)
1961 {
1962 PKG_MEM_ERROR;
1963 return -1;
1964 }
1965 memset(trn, 0, sizeof(tr_item_t));
1966 memcpy(&(trn->tre), e, sizeof(tr_export_t));
1967 trn->trid = trid;
1968
1969 //LM_DBG("TR class [%.*s] added to entry [%d]\n", e->tclass.len,
1970 // e->tclass.s, trid%TR_TABLE_SIZE);
1971 if(trj==0)
1972 {
1973 trn->next = _tr_table[trid%TR_TABLE_SIZE];
1974 _tr_table[trid%TR_TABLE_SIZE] = trn;
1975 goto done;
1976 }
1977 trn->next = trj->next;
1978 trj->next = trn;
1979
1980 done:
1981 return 0;
1982 }
1983
1984 /**
1985 *
1986 */
register_trans_mod(char * mod_name,tr_export_t * items)1987 int register_trans_mod(char *mod_name, tr_export_t *items)
1988 {
1989 int ret;
1990 int i;
1991
1992 if (items==0)
1993 return 0;
1994
1995 for ( i=0 ; items[i].tclass.s ; i++ ) {
1996 ret = tr_table_add(&items[i]);
1997 if (ret!=0) {
1998 LM_ERR("failed to register pseudo-variable <%.*s> for module %s\n",
1999 items[i].tclass.len, items[i].tclass.s, mod_name);
2000 }
2001 }
2002 return 0;
2003 }
2004
2005 /**
2006 *
2007 */
tr_table_free(void)2008 int tr_table_free(void)
2009 {
2010 tr_item_p te;
2011 tr_item_p te1;
2012 int i;
2013
2014 for(i=0; i<TR_TABLE_SIZE; i++)
2015 {
2016 te = _tr_table[i];
2017 while(te!=0)
2018 {
2019 te1 = te;
2020 te = te->next;
2021 pkg_free(te1);
2022 }
2023 }
2024 memset(_tr_table, 0, sizeof(tr_item_t*)*TR_TABLE_SIZE);
2025 _tr_table_set = 0;
2026
2027 return 0;
2028 }
2029
2030 /**
2031 *
2032 */
tr_lookup_class(str * tclass)2033 tr_export_t* tr_lookup_class(str *tclass)
2034 {
2035 tr_item_t *tri;
2036 unsigned int trid;
2037
2038 if(tclass==0 || tclass->s==0)
2039 {
2040 LM_ERR("bad parameters\n");
2041 return NULL;
2042 }
2043
2044 /* search in TR table */
2045 // trid = get_hash1_raw(tclass->s, tclass->len);
2046 trid = get_hash1_raw(tclass->s, tclass->len);
2047 tri = _tr_table[trid%TR_TABLE_SIZE];
2048 while(tri)
2049 {
2050 if(tri->trid==trid && tri->tre.tclass.len==tclass->len
2051 && memcmp(tri->tre.tclass.s, tclass->s, tclass->len)==0)
2052 return &(tri->tre);
2053 tri = tri->next;
2054 }
2055
2056 return NULL;
2057 }
2058
2059
2060 /********************************************************
2061 * core PVs, initialization and destroy APIs
2062 ********************************************************/
2063
2064 static pv_export_t _core_pvs[] = {
2065 {{"null", (sizeof("null")-1)}, /* */
2066 PVT_NULL, pv_get_null, 0,
2067 0, 0, 0, 0},
2068
2069 { {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
2070 };
2071
2072 /** init pv api (optional).
2073 * @return 0 on success, -1 on error
2074 */
pv_init_api(void)2075 int pv_init_api(void)
2076 {
2077 pv_init_table();
2078 tr_init_table();
2079 if(pv_init_buffer()<0)
2080 return -1;
2081
2082 pv_str_empty_buf[0] = '\0';
2083 pv_str_empty_buf[1] = '\0';
2084 pv_str_empty.s = pv_str_empty_buf;
2085 strcpy(pv_str_null_buf, PV_STR_NULL_VAL);
2086 pv_str_null.s = pv_str_null_buf;
2087
2088 if(register_pvars_mod("core", _core_pvs)<0)
2089 return -1;
2090 return 0;
2091 }
2092
2093
2094 /** destroy pv api. */
pv_destroy_api(void)2095 void pv_destroy_api(void)
2096 {
2097 /* free PV and TR hash tables */
2098 pv_table_free();
2099 tr_table_free();
2100 pv_destroy_buffer();
2101 return;
2102 }
2103
2104 /**
2105 * - buffer to print PVs
2106 */
2107 static char **_pv_print_buffer = NULL;
2108 #define PV_DEFAULT_PRINT_BUFFER_SIZE 8192 /* 8kB */
2109 static int _pv_print_buffer_size = PV_DEFAULT_PRINT_BUFFER_SIZE;
2110 static int _pv_print_buffer_size_active = 0;
2111 /* 6 mod params + 4 direct usage from mods */
2112 #define PV_DEFAULT_PRINT_BUFFER_SLOTS 40
2113 static int _pv_print_buffer_slots = PV_DEFAULT_PRINT_BUFFER_SLOTS;
2114 static int _pv_print_buffer_slots_active = 0;
2115 static int _pv_print_buffer_index = 0;
2116
2117 /**
2118 *
2119 */
pv_init_buffer(void)2120 int pv_init_buffer(void)
2121 {
2122 int i;
2123
2124 /* already initialized ?!? */
2125 if(_pv_print_buffer!=NULL)
2126 return 0;
2127
2128 _pv_print_buffer =
2129 (char**)pkg_malloc(_pv_print_buffer_slots*sizeof(char*));
2130 if(_pv_print_buffer==NULL)
2131 {
2132 PKG_MEM_ERROR;
2133 return -1;
2134 }
2135 memset(_pv_print_buffer, 0, _pv_print_buffer_slots*sizeof(char*));
2136 for(i=0; i<_pv_print_buffer_slots; i++)
2137 {
2138 _pv_print_buffer[i] =
2139 (char*)pkg_malloc(_pv_print_buffer_size*sizeof(char));
2140 if(_pv_print_buffer[i]==NULL)
2141 {
2142 PKG_MEM_ERROR;
2143 return -1;
2144 }
2145 }
2146 LM_DBG("PV print buffer initialized to [%d][%d]\n",
2147 _pv_print_buffer_slots, _pv_print_buffer_size);
2148 _pv_print_buffer_slots_active = _pv_print_buffer_slots;
2149 _pv_print_buffer_size_active = _pv_print_buffer_size;
2150
2151 return 0;
2152 }
2153
2154 /**
2155 *
2156 */
pv_destroy_buffer(void)2157 void pv_destroy_buffer(void)
2158 {
2159 int i;
2160
2161 if(_pv_print_buffer==NULL)
2162 return;
2163 for(i=0; i<_pv_print_buffer_slots_active; i++)
2164 {
2165 if(_pv_print_buffer[i]!=NULL)
2166 pkg_free(_pv_print_buffer[i]);
2167 }
2168 pkg_free(_pv_print_buffer);
2169 _pv_print_buffer_slots_active = 0;
2170 _pv_print_buffer_size_active = 0;
2171 _pv_print_buffer = NULL;
2172 }
2173
2174 /**
2175 *
2176 */
pv_reinit_buffer(void)2177 int pv_reinit_buffer(void)
2178 {
2179 if(_pv_print_buffer_size==_pv_print_buffer_size_active
2180 && _pv_print_buffer_slots==_pv_print_buffer_slots_active)
2181 return 0;
2182 pv_destroy_buffer();
2183 return pv_init_buffer();
2184 }
2185
2186 /**
2187 *
2188 */
pv_get_buffer(void)2189 char* pv_get_buffer(void)
2190 {
2191 char *p;
2192
2193 p = _pv_print_buffer[_pv_print_buffer_index];
2194 _pv_print_buffer_index = (_pv_print_buffer_index+1)
2195 % _pv_print_buffer_slots_active;
2196
2197 return p;
2198 }
2199
2200 /**
2201 *
2202 */
pv_get_buffer_size(void)2203 int pv_get_buffer_size(void)
2204 {
2205 return _pv_print_buffer_size_active;
2206 }
2207
2208 /**
2209 *
2210 */
pv_get_buffer_slots(void)2211 int pv_get_buffer_slots(void)
2212 {
2213 return _pv_print_buffer_slots_active;
2214 }
2215
2216 /**
2217 *
2218 */
pv_set_buffer_size(int n)2219 void pv_set_buffer_size(int n)
2220 {
2221 _pv_print_buffer_size = n;
2222 if(_pv_print_buffer_size<=0)
2223 _pv_print_buffer_size = PV_DEFAULT_PRINT_BUFFER_SIZE;
2224 }
2225
2226 /**
2227 *
2228 */
pv_set_buffer_slots(int n)2229 void pv_set_buffer_slots(int n)
2230 {
2231 _pv_print_buffer_slots = n;
2232 if(_pv_print_buffer_slots<=0)
2233 _pv_print_buffer_slots = PV_DEFAULT_PRINT_BUFFER_SLOTS;
2234 }
2235