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