1 /*
2  * Copyright (C) 2009 Daniel-Constantin Mierla (asipto.com)
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 /*!
17  * \file
18  * \brief Kamailio core :: Extended AVPs
19  * \ingroup core
20  * Module: \ref core
21  */
22 
23 #include <stdio.h>
24 #include <string.h>
25 
26 #include "mem/mem.h"
27 #include "mem/shm_mem.h"
28 #include "dprint.h"
29 #include "hashes.h"
30 #include "xavp.h"
31 
32 /*! XAVP list head */
33 static sr_xavp_t *_xavp_list_head = 0;
34 /*! Pointer to XAVP current list */
35 static sr_xavp_t **_xavp_list_crt = &_xavp_list_head;
36 
37 /*! XAVU list head */
38 static sr_xavp_t *_xavu_list_head = 0;
39 /*! Pointer to XAVP current list */
40 static sr_xavp_t **_xavu_list_crt = &_xavu_list_head;
41 
42 /*! XAVI list head */
43 static sr_xavp_t *_xavi_list_head = 0;
44 /*! Pointer to XAVI current list */
45 static sr_xavp_t **_xavi_list_crt = &_xavi_list_head;
46 
47 /*! Helper functions */
48 static sr_xavp_t *xavp_get_internal(str *name, sr_xavp_t **list, int idx, sr_xavp_t **prv);
49 static int xavp_rm_internal(str *name, sr_xavp_t **head, int idx);
50 
51 
xavp_shm_free(void * p)52 void xavp_shm_free(void *p)
53 {
54 	shm_free(p);
55 }
56 
xavp_shm_free_unsafe(void * p)57 void xavp_shm_free_unsafe(void *p)
58 {
59 	shm_free_unsafe(p);
60 }
61 
62 
xavp_free(sr_xavp_t * xa)63 void xavp_free(sr_xavp_t *xa)
64 {
65 	if(xa==NULL) {
66 		return;
67 	}
68 	if(xa->val.type == SR_XTYPE_DATA) {
69 		if(xa->val.v.data!=NULL && xa->val.v.data->pfree!=NULL) {
70 			xa->val.v.data->pfree(xa->val.v.data->p, xavp_shm_free);
71 			shm_free(xa->val.v.data);
72 		}
73 	} else if(xa->val.type == SR_XTYPE_SPTR) {
74 		if(xa->val.v.vptr) {
75 			shm_free(xa->val.v.vptr);
76 		}
77 	} else if(xa->val.type == SR_XTYPE_XAVP) {
78 		xavp_destroy_list(&xa->val.v.xavp);
79 	}
80 	shm_free(xa);
81 }
82 
xavp_free_unsafe(sr_xavp_t * xa)83 void xavp_free_unsafe(sr_xavp_t *xa)
84 {
85 	if(xa==NULL) {
86 		return;
87 	}
88 	if(xa->val.type == SR_XTYPE_DATA) {
89 		if(xa->val.v.data!=NULL && xa->val.v.data->pfree!=NULL) {
90 			xa->val.v.data->pfree(xa->val.v.data->p, xavp_shm_free_unsafe);
91 			shm_free_unsafe(xa->val.v.data);
92 		}
93 	} else if(xa->val.type == SR_XTYPE_SPTR) {
94 		if(xa->val.v.vptr) {
95 			shm_free_unsafe(xa->val.v.vptr);
96 		}
97 	} else if(xa->val.type == SR_XTYPE_XAVP) {
98 		xavp_destroy_list_unsafe(&xa->val.v.xavp);
99 	}
100 	shm_free_unsafe(xa);
101 }
102 
xavp_new_value(str * name,sr_xval_t * val)103 static sr_xavp_t *xavp_new_value(str *name, sr_xval_t *val)
104 {
105 	sr_xavp_t *avp;
106 	int size;
107 	unsigned int id;
108 
109 	if(name==NULL || name->s==NULL || val==NULL)
110 		return NULL;
111 	id = get_hash1_raw(name->s, name->len);
112 
113 	size = sizeof(sr_xavp_t) + name->len + 1;
114 	if(val->type == SR_XTYPE_STR)
115 		size += val->v.s.len + 1;
116 	avp = (sr_xavp_t*)shm_malloc(size);
117 	if(avp==NULL) {
118 		SHM_MEM_ERROR;
119 		return NULL;
120 	}
121 	memset(avp, 0, size);
122 	avp->id = id;
123 	avp->name.s = (char*)avp + sizeof(sr_xavp_t);
124 	memcpy(avp->name.s, name->s, name->len);
125 	avp->name.s[name->len] = '\0';
126 	avp->name.len = name->len;
127 	memcpy(&avp->val, val, sizeof(sr_xval_t));
128 	if(val->type == SR_XTYPE_STR)
129 	{
130 		avp->val.v.s.s = avp->name.s + avp->name.len + 1;
131 		memcpy(avp->val.v.s.s, val->v.s.s, val->v.s.len);
132 		avp->val.v.s.s[val->v.s.len] = '\0';
133 		avp->val.v.s.len = val->v.s.len;
134 	}
135 
136 	return avp;
137 }
138 
xavp_add(sr_xavp_t * xavp,sr_xavp_t ** list)139 int xavp_add(sr_xavp_t *xavp, sr_xavp_t **list)
140 {
141 	if (xavp==NULL) {
142 		return -1;
143 	}
144 	/* Prepend new xavp to the list */
145 	if(list) {
146 		xavp->next = *list;
147 		*list = xavp;
148 	} else {
149 		xavp->next = *_xavp_list_crt;
150 		*_xavp_list_crt = xavp;
151 	}
152 
153 	return 0;
154 }
155 
xavp_add_last(sr_xavp_t * xavp,sr_xavp_t ** list)156 int xavp_add_last(sr_xavp_t *xavp, sr_xavp_t **list)
157 {
158 	sr_xavp_t *prev;
159 	sr_xavp_t *crt;
160 
161 	if (xavp==NULL) {
162 		return -1;
163 	}
164 
165 	crt = xavp_get_internal(&xavp->name, list, 0, 0);
166 
167 	prev = NULL;
168 
169 	while(crt) {
170 		prev = crt;
171 		crt = xavp_get_next(prev);
172 	}
173 
174 	if(prev==NULL) {
175 		/* Prepend new xavp to the list */
176 		if(list) {
177 			xavp->next = *list;
178 			*list = xavp;
179 		} else {
180 			xavp->next = *_xavp_list_crt;
181 			*_xavp_list_crt = xavp;
182 		}
183 	} else {
184 		xavp->next = prev->next;
185 		prev->next = xavp;
186 	}
187 
188 	return 0;
189 }
190 
xavp_add_after(sr_xavp_t * nxavp,sr_xavp_t * pxavp)191 int xavp_add_after(sr_xavp_t *nxavp, sr_xavp_t *pxavp)
192 {
193 	if (nxavp==NULL) {
194 		return -1;
195 	}
196 
197 	if(pxavp==NULL) {
198 		nxavp->next = *_xavp_list_crt;
199 		*_xavp_list_crt = nxavp;
200 	} else {
201 		nxavp->next = pxavp->next;
202 		pxavp->next = nxavp;
203 	}
204 
205 	return 0;
206 }
207 
xavp_add_value(str * name,sr_xval_t * val,sr_xavp_t ** list)208 sr_xavp_t *xavp_add_value(str *name, sr_xval_t *val, sr_xavp_t **list)
209 {
210 	sr_xavp_t *avp=0;
211 
212 	avp = xavp_new_value(name, val);
213 	if (avp==NULL)
214 		return NULL;
215 
216 	/* Prepend new value to the list */
217 	if(list) {
218 		avp->next = *list;
219 		*list = avp;
220 	} else {
221 		avp->next = *_xavp_list_crt;
222 		*_xavp_list_crt = avp;
223 	}
224 
225 	return avp;
226 }
227 
xavp_add_value_after(str * name,sr_xval_t * val,sr_xavp_t * pxavp)228 sr_xavp_t *xavp_add_value_after(str *name, sr_xval_t *val, sr_xavp_t *pxavp)
229 {
230 	sr_xavp_t *avp=0;
231 
232 	avp = xavp_new_value(name, val);
233 	if (avp==NULL)
234 		return NULL;
235 
236 	/* link new xavp */
237 	if(pxavp) {
238 		avp->next = pxavp->next;
239 		pxavp->next = avp;
240 	} else {
241 		avp->next = *_xavp_list_crt;
242 		*_xavp_list_crt = avp;
243 	}
244 
245 	return avp;
246 }
247 
xavp_add_xavp_value(str * rname,str * name,sr_xval_t * val,sr_xavp_t ** list)248 sr_xavp_t *xavp_add_xavp_value(str *rname, str *name, sr_xval_t *val, sr_xavp_t **list)
249 {
250 	sr_xavp_t *ravp=0;
251 	sr_xavp_t *cavp=0;
252 	sr_xval_t rval;
253 
254 	cavp = xavp_new_value(name, val);
255 	if (cavp==NULL)
256 		return NULL;
257 
258 	memset(&rval, 0, sizeof(sr_xval_t));
259 	rval.type = SR_XTYPE_XAVP;
260 	rval.v.xavp = cavp;
261 
262 	ravp = xavp_new_value(rname, &rval);
263 	if (ravp==NULL) {
264 		xavp_destroy_list(&cavp);
265 		return NULL;
266 	}
267 
268 	/* Prepend new value to the list */
269 	if(list) {
270 		ravp->next = *list;
271 		*list = ravp;
272 	} else {
273 		ravp->next = *_xavp_list_crt;
274 		*_xavp_list_crt = ravp;
275 	}
276 
277 	return ravp;
278 }
279 
xavp_set_value(str * name,int idx,sr_xval_t * val,sr_xavp_t ** list)280 sr_xavp_t *xavp_set_value(str *name, int idx, sr_xval_t *val, sr_xavp_t **list)
281 {
282 	sr_xavp_t *avp;
283 	sr_xavp_t *cur;
284 	sr_xavp_t *prv=0;
285 
286 	if(val==NULL)
287 		return NULL;
288 
289 	/* Find the current value */
290 	cur = xavp_get_internal(name, list, idx, &prv);
291 	if(cur==NULL)
292 		return NULL;
293 
294 	avp = xavp_new_value(name, val);
295 	if (avp==NULL)
296 		return NULL;
297 
298 	/* Replace the current value with the new */
299 	avp->next = cur->next;
300 	if(prv)
301 		prv->next = avp;
302 	else if(list)
303 		*list = avp;
304 	else
305 		*_xavp_list_crt = avp;
306 
307 	xavp_free(cur);
308 
309 	return avp;
310 }
311 
xavp_get_internal(str * name,sr_xavp_t ** list,int idx,sr_xavp_t ** prv)312 static sr_xavp_t *xavp_get_internal(str *name, sr_xavp_t **list, int idx, sr_xavp_t **prv)
313 {
314 	sr_xavp_t *avp;
315 	unsigned int id;
316 	int n = 0;
317 
318 	if(name==NULL || name->s==NULL)
319 		return NULL;
320 	id = get_hash1_raw(name->s, name->len);
321 
322 	if(list && *list)
323 		avp = *list;
324 	else
325 		avp = *_xavp_list_crt;
326 	while(avp)
327 	{
328 		if(avp->id==id && avp->name.len==name->len
329 				&& strncmp(avp->name.s, name->s, name->len)==0)
330 		{
331 			if(idx==n)
332 				return avp;
333 			n++;
334 		}
335 		if(prv)
336 			*prv = avp;
337 		avp = avp->next;
338 	}
339 	return NULL;
340 }
341 
xavp_get(str * name,sr_xavp_t * start)342 sr_xavp_t *xavp_get(str *name, sr_xavp_t *start)
343 {
344 	return xavp_get_internal(name, (start)?&start:NULL, 0, NULL);
345 }
346 
xavp_get_by_index(str * name,int idx,sr_xavp_t ** start)347 sr_xavp_t *xavp_get_by_index(str *name, int idx, sr_xavp_t **start)
348 {
349 	return xavp_get_internal(name, start, idx, NULL);
350 }
351 
xavp_get_next(sr_xavp_t * start)352 sr_xavp_t *xavp_get_next(sr_xavp_t *start)
353 {
354 	sr_xavp_t *avp;
355 
356 	if(start==NULL)
357 		return NULL;
358 
359 	avp = start->next;
360 	while(avp)
361 	{
362 		if(avp->id==start->id && avp->name.len==start->name.len
363 				&& strncmp(avp->name.s, start->name.s, start->name.len)==0)
364 			return avp;
365 		avp=avp->next;
366 	}
367 
368 	return NULL;
369 }
370 
xavp_get_last(str * xname,sr_xavp_t ** list)371 sr_xavp_t *xavp_get_last(str *xname, sr_xavp_t **list)
372 {
373 	sr_xavp_t *prev;
374 	sr_xavp_t *crt;
375 
376 	crt = xavp_get_internal(xname, list, 0, 0);
377 
378 	prev = NULL;
379 
380 	while(crt) {
381 		prev = crt;
382 		crt = xavp_get_next(prev);
383 	}
384 
385 	return prev;
386 }
387 
xavp_rm(sr_xavp_t * xa,sr_xavp_t ** head)388 int xavp_rm(sr_xavp_t *xa, sr_xavp_t **head)
389 {
390 	sr_xavp_t *avp;
391 	sr_xavp_t *prv=0;
392 
393 	if(head!=NULL)
394 		avp = *head;
395 	else
396 		avp=*_xavp_list_crt;
397 
398 	while(avp)
399 	{
400 		if(avp==xa)
401 		{
402 			if(prv)
403 				prv->next=avp->next;
404 			else if(head!=NULL)
405 				*head = avp->next;
406 			else
407 				*_xavp_list_crt = avp->next;
408 			xavp_free(avp);
409 			return 1;
410 		}
411 		prv=avp; avp=avp->next;
412 	}
413 	return 0;
414 }
415 
416 /* Remove xavps
417  * idx: <0 remove all xavps with the same name
418  *      >=0 remove only the specified index xavp
419  * Returns number of xavps that were deleted
420  */
xavp_rm_internal(str * name,sr_xavp_t ** head,int idx)421 static int xavp_rm_internal(str *name, sr_xavp_t **head, int idx)
422 {
423 	sr_xavp_t *avp;
424 	sr_xavp_t *foo;
425 	sr_xavp_t *prv=0;
426 	unsigned int id;
427 	int n=0;
428 	int count=0;
429 
430 	if(name==NULL || name->s==NULL)
431 		return 0;
432 
433 	id = get_hash1_raw(name->s, name->len);
434 	if(head!=NULL)
435 		avp = *head;
436 	else
437 		avp = *_xavp_list_crt;
438 	while(avp)
439 	{
440 		foo = avp;
441 		avp=avp->next;
442 		if(foo->id==id && foo->name.len==name->len
443 				&& strncmp(foo->name.s, name->s, name->len)==0)
444 		{
445 			if(idx<0 || idx==n)
446 			{
447 				if(prv!=NULL)
448 					prv->next=foo->next;
449 				else if(head!=NULL)
450 					*head = foo->next;
451 				else
452 					*_xavp_list_crt = foo->next;
453 				xavp_free(foo);
454 				if(idx>=0)
455 					return 1;
456 				count++;
457 			} else {
458 				prv = foo;
459 			}
460 			n++;
461 		} else {
462 			prv = foo;
463 		}
464 	}
465 	return count;
466 }
467 
xavp_rm_by_name(str * name,int all,sr_xavp_t ** head)468 int xavp_rm_by_name(str *name, int all, sr_xavp_t **head)
469 {
470 	return xavp_rm_internal(name, head, -1*all);
471 }
472 
xavp_rm_by_index(str * name,int idx,sr_xavp_t ** head)473 int xavp_rm_by_index(str *name, int idx, sr_xavp_t **head)
474 {
475 	if (idx<0)
476 		return 0;
477 	return xavp_rm_internal(name, head, idx);
478 }
479 
xavp_rm_child_by_index(str * rname,str * cname,int idx)480 int xavp_rm_child_by_index(str *rname, str *cname, int idx)
481 {
482 	sr_xavp_t *avp=NULL;
483 
484 	if (idx<0) {
485 		return 0;
486 	}
487 	avp = xavp_get(rname, NULL);
488 
489 	if(avp == NULL || avp->val.type!=SR_XTYPE_XAVP) {
490 		return 0;
491 	}
492 	return xavp_rm_internal(cname, &avp->val.v.xavp, idx);
493 }
494 
xavp_count(str * name,sr_xavp_t ** start)495 int xavp_count(str *name, sr_xavp_t **start)
496 {
497 	sr_xavp_t *avp;
498 	unsigned int id;
499 	int n = 0;
500 
501 	if(name==NULL || name->s==NULL)
502 		return -1;
503 	id = get_hash1_raw(name->s, name->len);
504 
505 	if(start)
506 		avp = *start;
507 	else
508 		avp=*_xavp_list_crt;
509 	while(avp)
510 	{
511 		if(avp->id==id && avp->name.len==name->len
512 				&& strncmp(avp->name.s, name->s, name->len)==0)
513 		{
514 			n++;
515 		}
516 		avp=avp->next;
517 	}
518 
519 	return n;
520 }
521 
xavp_destroy_list_unsafe(sr_xavp_t ** head)522 void xavp_destroy_list_unsafe(sr_xavp_t **head)
523 {
524 	sr_xavp_t *avp, *foo;
525 
526 	avp = *head;
527 	while(avp)
528 	{
529 		foo = avp;
530 		avp = avp->next;
531 		xavp_free_unsafe(foo);
532 	}
533 	*head = 0;
534 }
535 
536 
xavp_destroy_list(sr_xavp_t ** head)537 void xavp_destroy_list(sr_xavp_t **head)
538 {
539 	sr_xavp_t *avp, *foo;
540 
541 	LM_DBG("destroying xavp list %p\n", *head);
542 	avp = *head;
543 	while(avp)
544 	{
545 		foo = avp;
546 		avp = avp->next;
547 		xavp_free(foo);
548 	}
549 	*head = 0;
550 }
551 
552 
xavp_reset_list(void)553 void xavp_reset_list(void)
554 {
555 	assert(_xavp_list_crt!=0 );
556 
557 	if (_xavp_list_crt!=&_xavp_list_head)
558 		_xavp_list_crt=&_xavp_list_head;
559 	xavp_destroy_list(_xavp_list_crt);
560 }
561 
562 
xavp_set_list(sr_xavp_t ** head)563 sr_xavp_t **xavp_set_list(sr_xavp_t **head)
564 {
565 	sr_xavp_t **avp;
566 
567 	assert(_xavp_list_crt!=0);
568 
569 	avp = _xavp_list_crt;
570 	_xavp_list_crt = head;
571 	return avp;
572 }
573 
xavp_get_crt_list(void)574 sr_xavp_t **xavp_get_crt_list(void)
575 {
576 	assert(_xavp_list_crt!=0);
577 	return _xavp_list_crt;
578 }
579 
xavx_print_list_content(char * name,sr_xavp_t ** head,sr_xavp_t ** rlist,int level)580 void xavx_print_list_content(char *name, sr_xavp_t **head, sr_xavp_t **rlist, int level)
581 {
582 	sr_xavp_t *avp=0;
583 	sr_xavp_t *start=0;
584 
585 	if(head!=NULL) {
586 		start = *head;
587 	} else {
588 		start=*rlist;
589 	}
590 	LM_INFO("+++++ start %s list: %p (%p) (level=%d)\n", name, start, head, level);
591 	avp = start;
592 	while(avp)
593 	{
594 		LM_INFO("     *** (l:%d - %p) %s name: %s\n", level, avp, name, avp->name.s);
595 		LM_INFO("     %s id: %u\n", name, avp->id);
596 		LM_INFO("     %s value type: %d\n", name, avp->val.type);
597 		switch(avp->val.type) {
598 			case SR_XTYPE_NULL:
599 				LM_INFO("     %s value: <null>\n", name);
600 			break;
601 			case SR_XTYPE_INT:
602 				LM_INFO("     %s value (int): %d\n", name, avp->val.v.i);
603 			break;
604 			case SR_XTYPE_STR:
605 				LM_INFO("     %s value (str): %s\n", name, avp->val.v.s.s);
606 			break;
607 			case SR_XTYPE_TIME:
608 				LM_INFO("     %s value (time): %lu\n", name,
609 						(long unsigned int)avp->val.v.t);
610 			break;
611 			case SR_XTYPE_LONG:
612 				LM_INFO("     %s value (long): %ld\n", name, avp->val.v.l);
613 			break;
614 			case SR_XTYPE_LLONG:
615 				LM_INFO("     %s value (llong): %lld\n", name, avp->val.v.ll);
616 			break;
617 			case SR_XTYPE_XAVP:
618 				LM_INFO("     %s value: <xavp:%p>\n", name, avp->val.v.xavp);
619 				xavx_print_list_content(name, &avp->val.v.xavp, rlist, level+1);
620 			break;
621 			case SR_XTYPE_VPTR:
622 				LM_INFO("     %s value: <vptr:%p>\n", name, avp->val.v.vptr);
623 			break;
624 			case SR_XTYPE_SPTR:
625 				LM_INFO("     %s value: <sptr:%p>\n", name, avp->val.v.vptr);
626 			break;
627 			case SR_XTYPE_DATA:
628 				LM_INFO("     %s value: <data:%p>\n", name, avp->val.v.data);
629 			break;
630 		}
631 		LM_INFO("     *** (l:%d - %p) end\n", level, avp);
632 		avp = avp->next;
633 	}
634 	LM_INFO("----- end %s list: %p (level=%d)\n", name, start, level);
635 }
636 
xavp_print_list_content(sr_xavp_t ** head,int level)637 void xavp_print_list_content(sr_xavp_t **head, int level)
638 {
639 	xavx_print_list_content("XAVP", head, _xavp_list_crt, level);
640 }
641 
xavp_print_list(sr_xavp_t ** head)642 void xavp_print_list(sr_xavp_t **head)
643 {
644 	xavp_print_list_content(head, 0);
645 }
646 
647 /**
648  * returns a list of str with key names.
649  * Example:
650  * If we have this structure
651  * $xavp(test=>one) = 1
652  * $xavp(test[0]=>two) = "2"
653  * $xavp(test[0]=>three) = 3
654  * $xavp(test[0]=>four) = $xavp(whatever)
655  * $xavp(test[0]=>two) = "other 2"
656  *
657  * xavp_get_list_keys_names(test[0]) returns
658  * {"one", "two", "three", "four"}
659  *
660  * free the struct str_list afterwards
661  * but do *NO* free the strings inside
662  */
xavp_get_list_key_names(sr_xavp_t * xavp)663 struct str_list *xavp_get_list_key_names(sr_xavp_t *xavp)
664 {
665 	sr_xavp_t *avp = NULL;
666 	struct str_list *result = NULL;
667 	struct str_list *r = NULL;
668 	struct str_list *f = NULL;
669 	int total = 0;
670 
671 	if(xavp==NULL){
672 		LM_ERR("xavp is NULL\n");
673 		return 0;
674 	}
675 
676 	if(xavp->val.type!=SR_XTYPE_XAVP){
677 		LM_ERR("%s not xavp?\n", xavp->name.s);
678 		return 0;
679 	}
680 
681 	avp = xavp->val.v.xavp;
682 
683 	if (avp)
684 	{
685 		result = (struct str_list*)pkg_malloc(sizeof(struct str_list));
686 		if (result==NULL) {
687 			PKG_MEM_ERROR;
688 			return 0;
689 		}
690 		r = result;
691 		r->s.s = avp->name.s;
692 		r->s.len = avp->name.len;
693 		r->next = NULL;
694 		avp = avp->next;
695 	}
696 
697 	while(avp)
698 	{
699 		f = result;
700 		while(f)
701 		{
702 			if((avp->name.len==f->s.len)&&
703 				(strncmp(avp->name.s, f->s.s, f->s.len)==0))
704 			{
705 				break; /* name already on list */
706 			}
707 			f = f->next;
708 		}
709 		if (f==NULL)
710 		{
711 			r = append_str_list(avp->name.s, avp->name.len, &r, &total);
712 			if(r==NULL){
713 				while(result){
714 					r = result;
715 					result = result->next;
716 					pkg_free(r);
717 				}
718 				return 0;
719 			}
720 		}
721 		avp = avp->next;
722 	}
723 	return result;
724 }
725 
xavp_clone_level_nodata(sr_xavp_t * xold)726 sr_xavp_t *xavp_clone_level_nodata(sr_xavp_t *xold)
727 {
728 	return xavp_clone_level_nodata_with_new_name(xold, &xold->name);
729 }
730 
731 /**
732  * clone the xavp without values that are custom data
733  * - only one list level is cloned, other sublists are ignored
734  */
xavp_clone_level_nodata_with_new_name(sr_xavp_t * xold,str * dst_name)735 sr_xavp_t *xavp_clone_level_nodata_with_new_name(sr_xavp_t *xold, str *dst_name)
736 {
737 	sr_xavp_t *xnew = NULL;
738 	sr_xavp_t *navp = NULL;
739 	sr_xavp_t *oavp = NULL;
740 	sr_xavp_t *pavp = NULL;
741 
742 	if(xold == NULL)
743 	{
744 		return NULL;
745 	}
746 	if(xold->val.type==SR_XTYPE_DATA || xold->val.type==SR_XTYPE_SPTR)
747 	{
748 		LM_INFO("xavp value type is 'data' - ignoring in clone\n");
749 		return NULL;
750 	}
751 	xnew = xavp_new_value(dst_name, &xold->val);
752 	if(xnew==NULL)
753 	{
754 		LM_ERR("cannot create cloned root xavp\n");
755 		return NULL;
756 	}
757 	LM_DBG("cloned root xavp [%.*s] >> [%.*s]\n", xold->name.len, xold->name.s, dst_name->len, dst_name->s);
758 
759 	if(xold->val.type!=SR_XTYPE_XAVP)
760 	{
761 		return xnew;
762 	}
763 
764 	xnew->val.v.xavp = NULL;
765 	oavp = xold->val.v.xavp;
766 
767 	while(oavp)
768 	{
769 		if(oavp->val.type!=SR_XTYPE_DATA && oavp->val.type!=SR_XTYPE_XAVP
770 				&& oavp->val.type!=SR_XTYPE_SPTR)
771 		{
772 			navp =  xavp_new_value(&oavp->name, &oavp->val);
773 			if(navp==NULL)
774 			{
775 				LM_ERR("cannot create cloned embedded xavp\n");
776 				if(xnew->val.v.xavp != NULL) {
777 					xavp_destroy_list(&xnew->val.v.xavp);
778 				}
779 				shm_free(xnew);
780 				return NULL;
781 			}
782 			LM_DBG("cloned inner xavp [%.*s]\n", oavp->name.len, oavp->name.s);
783 			if(xnew->val.v.xavp == NULL)
784 			{
785 				/* link to val in head xavp */
786 				xnew->val.v.xavp = navp;
787 			} else {
788 				/* link to prev xavp in the list */
789 				pavp->next = navp;
790 			}
791 			pavp = navp;
792 		}
793 		oavp = oavp->next;
794 	}
795 
796 	if(xnew->val.v.xavp == NULL)
797 	{
798 		shm_free(xnew);
799 		return NULL;
800 	}
801 
802 	return xnew;
803 }
804 
xavp_insert(sr_xavp_t * xavp,int idx,sr_xavp_t ** list)805 int xavp_insert(sr_xavp_t *xavp, int idx, sr_xavp_t **list)
806 {
807 	sr_xavp_t *crt = 0;
808 	sr_xavp_t *lst = 0;
809 	sr_xval_t val;
810 	int n = 0;
811 	int i = 0;
812 
813 	if(xavp==NULL) {
814 		return -1;
815 	}
816 
817 	crt = xavp_get_internal(&xavp->name, list, 0, NULL);
818 
819 	if (idx == 0 && (!crt || crt->val.type != SR_XTYPE_NULL))
820 		return xavp_add(xavp, list);
821 
822 	while(crt!=NULL && n<idx) {
823 		lst = crt;
824 		n++;
825 		crt = xavp_get_next(lst);
826 	}
827 
828 	if (crt && crt->val.type == SR_XTYPE_NULL) {
829 		xavp->next = crt->next;
830 		crt->next = xavp;
831 
832 		xavp_rm(crt, list);
833 		return 0;
834 	}
835 
836 	memset(&val, 0, sizeof(sr_xval_t));
837 	val.type = SR_XTYPE_NULL;
838 	for(i=0; i<idx-n; i++) {
839 		crt = xavp_new_value(&xavp->name, &val);
840 		if(crt==NULL)
841 			return -1;
842 		if (lst == NULL) {
843 			xavp_add(crt, list);
844 		} else {
845 			crt->next = lst->next;
846 			lst->next = crt;
847 		}
848 		lst = crt;
849 	}
850 
851 	if(lst==NULL) {
852 		LM_ERR("cannot link the xavp\n");
853 		return -1;
854 	}
855 	xavp->next = lst->next;
856 	lst->next = xavp;
857 
858 	return 0;
859 }
860 
xavp_extract(str * name,sr_xavp_t ** list)861 sr_xavp_t *xavp_extract(str *name, sr_xavp_t **list)
862 {
863 	sr_xavp_t *avp = 0;
864 	sr_xavp_t *foo;
865 	sr_xavp_t *prv = 0;
866 	unsigned int id;
867 
868 	if(name==NULL || name->s==NULL) {
869 		if(list!=NULL) {
870 			avp = *list;
871 			if(avp!=NULL) {
872 				*list = avp->next;
873 				avp->next = NULL;
874 			}
875 		} else {
876 			avp = *_xavp_list_crt;
877 			if(avp!=NULL) {
878 				*_xavp_list_crt = avp->next;
879 				avp->next = NULL;
880 			}
881 		}
882 
883 		return avp;
884 	}
885 
886 	id = get_hash1_raw(name->s, name->len);
887 	if(list!=NULL)
888 		avp = *list;
889 	else
890 		avp = *_xavp_list_crt;
891 	while(avp)
892 	{
893 		foo = avp;
894 		avp=avp->next;
895 		if(foo->id==id && foo->name.len==name->len
896 				&& strncmp(foo->name.s, name->s, name->len)==0)
897 		{
898 			if(prv!=NULL)
899 				prv->next=foo->next;
900 			else if(list!=NULL)
901 				*list = foo->next;
902 			else
903 				*_xavp_list_crt = foo->next;
904 			foo->next = NULL;
905 			return foo;
906 		} else {
907 			prv = foo;
908 		}
909 	}
910 	return NULL;
911 }
912 
913 /**
914  * return child node of an xavp
915  * - $xavp(rname=>cname)
916  */
xavp_get_child(str * rname,str * cname)917 sr_xavp_t* xavp_get_child(str *rname, str *cname)
918 {
919 	sr_xavp_t *ravp=NULL;
920 
921 	ravp = xavp_get(rname, NULL);
922 	if(ravp==NULL || ravp->val.type!=SR_XTYPE_XAVP)
923 		return NULL;
924 
925 	return xavp_get(cname, ravp->val.v.xavp);
926 }
927 
928 
929 /**
930  * return child node of an xavp if it has int value
931  * - $xavp(rname=>cname)
932  */
xavp_get_child_with_ival(str * rname,str * cname)933 sr_xavp_t* xavp_get_child_with_ival(str *rname, str *cname)
934 {
935 	sr_xavp_t *vavp=NULL;
936 
937 	vavp = xavp_get_child(rname, cname);
938 
939 	if(vavp==NULL || vavp->val.type!=SR_XTYPE_INT)
940 		return NULL;
941 
942 	return vavp;
943 }
944 
945 
946 /**
947  * return child node of an xavp if it has string value
948  * - $xavp(rname=>cname)
949  */
xavp_get_child_with_sval(str * rname,str * cname)950 sr_xavp_t* xavp_get_child_with_sval(str *rname, str *cname)
951 {
952 	sr_xavp_t *vavp=NULL;
953 
954 	vavp = xavp_get_child(rname, cname);
955 
956 	if(vavp==NULL || vavp->val.type!=SR_XTYPE_STR)
957 		return NULL;
958 
959 	return vavp;
960 }
961 
962 /**
963  * Set the value of the first xavp rname with first child xavp cname
964  * - replace if it exits; add if it doesn't exist
965  * - config operations:
966  *   $xavp(rxname=>cname) = xval;
967  *     or:
968  *   $xavp(rxname[0]=>cname[0]) = xval;
969  */
xavp_set_child_xval(str * rname,str * cname,sr_xval_t * xval)970 int xavp_set_child_xval(str *rname, str *cname, sr_xval_t *xval)
971 {
972 	sr_xavp_t *ravp=NULL;
973 	sr_xavp_t *cavp=NULL;
974 
975 	ravp = xavp_get(rname, NULL);
976 	if(ravp) {
977 		if(ravp->val.type != SR_XTYPE_XAVP) {
978 			/* first root xavp does not have xavp list value - remove it */
979 			xavp_rm(ravp, NULL);
980 			/* add a new xavp in the root list with a child */
981 			if(xavp_add_xavp_value(rname, cname, xval, NULL)==NULL) {
982 				return -1;
983 			}
984 		} else {
985 			/* first root xavp has an xavp list value */
986 			cavp = xavp_get(cname, ravp->val.v.xavp);
987 			if(cavp) {
988 				/* child xavp with same name - remove it */
989 				/* todo: update in place for int or if allocated size fits */
990 				xavp_rm(cavp, &ravp->val.v.xavp);
991 			}
992 			if(xavp_add_value(cname, xval, &ravp->val.v.xavp)==NULL) {
993 				return -1;
994 			}
995 		}
996 	} else {
997 		/* no xavp with rname in root list found */
998 		if(xavp_add_xavp_value(rname, cname, xval, NULL)==NULL) {
999 			return -1;
1000 		}
1001 	}
1002 
1003 	return 0;
1004 }
1005 
1006 /**
1007  *
1008  */
xavp_set_child_ival(str * rname,str * cname,int ival)1009 int xavp_set_child_ival(str *rname, str *cname, int ival)
1010 {
1011 	sr_xval_t xval;
1012 
1013 	memset(&xval, 0, sizeof(sr_xval_t));
1014 	xval.type = SR_XTYPE_INT;
1015 	xval.v.i = ival;
1016 
1017 	return xavp_set_child_xval(rname, cname, &xval);
1018 }
1019 
1020 /**
1021  *
1022  */
xavp_set_child_sval(str * rname,str * cname,str * sval)1023 int xavp_set_child_sval(str *rname, str *cname, str *sval)
1024 {
1025 	sr_xval_t xval;
1026 
1027 	memset(&xval, 0, sizeof(sr_xval_t));
1028 	xval.type = SR_XTYPE_STR;
1029 	xval.v.s = *sval;
1030 
1031 	return xavp_set_child_xval(rname, cname, &xval);
1032 }
1033 
1034 /**
1035  * serialize the values in subfields of an xavp in name=value; format
1036  * - rname - name of the root list xavp
1037  * - obuf - buffer were to write the output
1038  * - olen - the size of obuf
1039  * return: 0 - not found; -1 - error; >0 - length of output
1040  */
1041 
xavp_serialize_fields(str * rname,char * obuf,int olen)1042 int xavp_serialize_fields(str *rname, char *obuf, int olen)
1043 {
1044 	sr_xavp_t *ravp = NULL;
1045 	sr_xavp_t *avp = NULL;
1046 	str ostr;
1047 	int rlen;
1048 
1049 	ravp = xavp_get(rname, NULL);
1050 	if(ravp==NULL || ravp->val.type!=SR_XTYPE_XAVP) {
1051 		/* not found or not holding subfields */
1052 		return 0;
1053 	}
1054 
1055 	rlen = 0;
1056 	ostr.s = obuf;
1057 	avp = ravp->val.v.xavp;
1058 	while(avp) {
1059 		switch(avp->val.type) {
1060 			case SR_XTYPE_INT:
1061 				LM_DBG("     XAVP int value: %d\n", avp->val.v.i);
1062 				ostr.len = snprintf(ostr.s, olen-rlen, "%.*s=%u;",
1063 						avp->name.len, avp->name.s, (unsigned int)avp->val.v.i);
1064 				if(ostr.len<=0 || ostr.len>=olen-rlen) {
1065 					LM_ERR("failed to serialize int value (%d/%d\n",
1066 							ostr.len, olen-rlen);
1067 					return -1;
1068 				}
1069 			break;
1070 			case SR_XTYPE_STR:
1071 				LM_DBG("     XAVP str value: %s\n", avp->val.v.s.s);
1072 				if(avp->val.v.s.len == 0) {
1073 					ostr.len = snprintf(ostr.s, olen-rlen, "%.*s;",
1074 						avp->name.len, avp->name.s);
1075 				} else {
1076 					ostr.len = snprintf(ostr.s, olen-rlen, "%.*s=%.*s;",
1077 						avp->name.len, avp->name.s,
1078 						avp->val.v.s.len, avp->val.v.s.s);
1079 				}
1080 				if(ostr.len<=0 || ostr.len>=olen-rlen) {
1081 					LM_ERR("failed to serialize int value (%d/%d\n",
1082 							ostr.len, olen-rlen);
1083 					return -1;
1084 				}
1085 			break;
1086 			default:
1087 				LM_DBG("skipping value type: %d\n", avp->val.type);
1088 				ostr.len = 0;
1089 		}
1090 		if(ostr.len>0) {
1091 			ostr.s += ostr.len;
1092 			rlen += ostr.len;
1093 		}
1094 		avp = avp->next;
1095 	}
1096 	return rlen;
1097 }
1098 
1099 /**
1100  *
1101  */
1102 /*** XAVU - eXtended Attribute Value Unique pair - implementation ***/
1103 
1104 /**
1105  *
1106  */
xavu_print_list_content(sr_xavp_t ** head,int level)1107 void xavu_print_list_content(sr_xavp_t **head, int level)
1108 {
1109 	xavx_print_list_content("XAVU", head, _xavu_list_crt, level);
1110 }
1111 
xavu_print_list(sr_xavp_t ** head)1112 void xavu_print_list(sr_xavp_t **head)
1113 {
1114 	xavu_print_list_content(head, 0);
1115 }
1116 
1117 /**
1118  *
1119  */
xavu_reset_list(void)1120 void xavu_reset_list(void)
1121 {
1122 	assert(_xavu_list_crt!=0 );
1123 
1124 	if (_xavu_list_crt!=&_xavu_list_head)
1125 		_xavu_list_crt=&_xavu_list_head;
1126 	xavp_destroy_list(_xavu_list_crt);
1127 }
1128 
1129 /**
1130  *
1131  */
xavu_set_list(sr_xavp_t ** head)1132 sr_xavp_t **xavu_set_list(sr_xavp_t **head)
1133 {
1134 	sr_xavp_t **avu;
1135 
1136 	assert(_xavu_list_crt!=0);
1137 
1138 	avu = _xavu_list_crt;
1139 	_xavu_list_crt = head;
1140 	return avu;
1141 }
1142 
1143 /**
1144  *
1145  */
xavu_get_crt_list(void)1146 sr_xavp_t **xavu_get_crt_list(void)
1147 {
1148 	assert(_xavu_list_crt!=0);
1149 	return _xavu_list_crt;
1150 }
1151 
1152 /**
1153  *
1154  */
xavu_get_internal(str * name,sr_xavp_t ** list,sr_xavp_t ** prv)1155 static sr_xavp_t *xavu_get_internal(str *name, sr_xavp_t **list, sr_xavp_t **prv)
1156 {
1157 	sr_xavp_t *avu;
1158 	unsigned int id;
1159 
1160 	if(name==NULL || name->s==NULL) {
1161 		return NULL;
1162 	}
1163 
1164 	id = get_hash1_raw(name->s, name->len);
1165 
1166 	if(list && *list) {
1167 		avu = *list;
1168 	} else {
1169 		avu = *_xavu_list_crt;
1170 	}
1171 	while(avu) {
1172 		if(avu->id==id && avu->name.len==name->len
1173 				&& strncmp(avu->name.s, name->s, name->len)==0) {
1174 			return avu;
1175 		}
1176 		if(prv) {
1177 			*prv = avu;
1178 		}
1179 		avu = avu->next;
1180 	}
1181 	return NULL;
1182 }
1183 
1184 /**
1185  *
1186  */
xavu_get(str * name,sr_xavp_t * start)1187 sr_xavp_t *xavu_get(str *name, sr_xavp_t *start)
1188 {
1189 	return xavu_get_internal(name, (start)?&start:NULL, NULL);
1190 }
1191 
xavu_lookup(str * name,sr_xavp_t ** start)1192 sr_xavp_t *xavu_lookup(str *name, sr_xavp_t **start)
1193 {
1194 	return xavu_get_internal(name, start, NULL);
1195 }
1196 
1197 /**
1198  *
1199  */
xavu_rm(sr_xavp_t * xa,sr_xavp_t ** head)1200 int xavu_rm(sr_xavp_t *xa, sr_xavp_t **head)
1201 {
1202 	sr_xavp_t *avu;
1203 	sr_xavp_t *prv=0;
1204 
1205 	if(head!=NULL)
1206 		avu = *head;
1207 	else
1208 		avu=*_xavu_list_crt;
1209 
1210 	while(avu) {
1211 		if(avu==xa) {
1212 			if(prv) {
1213 				prv->next=avu->next;
1214 			} else if(head!=NULL) {
1215 				*head = avu->next;
1216 			} else {
1217 				*_xavu_list_crt = avu->next;
1218 			}
1219 			xavp_free(avu);
1220 			return 1;
1221 		}
1222 		prv=avu; avu=avu->next;
1223 	}
1224 	return 0;
1225 }
1226 
1227 /**
1228  *
1229  */
xavu_rm_by_name(str * name,sr_xavp_t ** head)1230 int xavu_rm_by_name(str *name, sr_xavp_t **head)
1231 {
1232 	sr_xavp_t *avu;
1233 	sr_xavp_t *foo;
1234 	sr_xavp_t *prv=0;
1235 	unsigned int id;
1236 
1237 
1238 	if(name==NULL || name->s==NULL) {
1239 		return -1;
1240 	}
1241 
1242 	id = get_hash1_raw(name->s, name->len);
1243 	if(head!=NULL) {
1244 		avu = *head;
1245 	} else {
1246 		avu = *_xavu_list_crt;
1247 	}
1248 	while(avu) {
1249 		foo = avu;
1250 		avu = avu->next;
1251 		if(foo->id==id && foo->name.len==name->len
1252 				&& strncmp(foo->name.s, name->s, name->len)==0) {
1253 			if(prv!=NULL) {
1254 				prv->next=foo->next;
1255 			} else if(head!=NULL) {
1256 				*head = foo->next;
1257 			} else {
1258 				*_xavu_list_crt = foo->next;
1259 			}
1260 			xavp_free(foo);
1261 		} else {
1262 			prv = foo;
1263 		}
1264 	}
1265 	return 0;
1266 }
1267 
1268 /**
1269  *
1270  */
xavu_rm_child_by_name(str * rname,str * cname)1271 int xavu_rm_child_by_name(str *rname, str *cname)
1272 {
1273 	sr_xavp_t *avu=NULL;
1274 
1275 	avu = xavu_lookup(rname, NULL);
1276 
1277 	if(avu == NULL || avu->val.type!=SR_XTYPE_XAVP) {
1278 		return 0;
1279 	}
1280 	return xavu_rm_by_name(cname, &avu->val.v.xavp);
1281 }
1282 
1283 /**
1284  *
1285  */
xavu_set_xval(str * name,sr_xval_t * val,sr_xavp_t ** list)1286 sr_xavp_t *xavu_set_xval(str *name, sr_xval_t *val, sr_xavp_t **list)
1287 {
1288 	sr_xavp_t *avu;
1289 	sr_xavp_t *crt;
1290 	sr_xavp_t *prv=0;
1291 
1292 	if(val==NULL) {
1293 		return NULL;
1294 	}
1295 
1296 	avu = xavp_new_value(name, val);
1297 	if (avu==NULL) {
1298 		return NULL;
1299 	}
1300 
1301 	/* find the current value */
1302 	crt = xavu_get_internal(name, list, &prv);
1303 	if(crt==NULL) {
1304 		/* add a new one in the list */
1305 		avu->next = *_xavu_list_crt;
1306 		*_xavu_list_crt = avu;
1307 		return avu;
1308 	}
1309 
1310 	/* replace the current value with the new */
1311 	avu->next = crt->next;
1312 	if(prv) {
1313 		prv->next = avu;
1314 	} else if(list) {
1315 		*list = avu;
1316 	} else {
1317 		*_xavu_list_crt = avu;
1318 	}
1319 
1320 	xavp_free(crt);
1321 
1322 	return avu;
1323 }
1324 
1325 /**
1326  *
1327  */
xavu_set_ival(str * rname,int ival)1328 sr_xavp_t *xavu_set_ival(str *rname, int ival)
1329 {
1330 	sr_xval_t xval;
1331 
1332 	memset(&xval, 0, sizeof(sr_xval_t));
1333 	xval.type = SR_XTYPE_INT;
1334 	xval.v.i = ival;
1335 
1336 	return xavu_set_xval(rname, &xval, NULL);
1337 }
1338 
1339 /**
1340  *
1341  */
xavu_set_sval(str * rname,str * sval)1342 sr_xavp_t *xavu_set_sval(str *rname, str *sval)
1343 {
1344 	sr_xval_t xval;
1345 
1346 	memset(&xval, 0, sizeof(sr_xval_t));
1347 	xval.type = SR_XTYPE_STR;
1348 	xval.v.s = *sval;
1349 
1350 	return xavu_set_xval(rname, &xval, NULL);
1351 }
1352 
1353 /**
1354  *
1355  */
xavu_set_xavu_value(str * rname,str * name,sr_xval_t * val,sr_xavp_t ** list)1356 sr_xavp_t *xavu_set_xavu_value(str *rname, str *name, sr_xval_t *val, sr_xavp_t **list)
1357 {
1358 	sr_xavp_t *ravu=0;
1359 	sr_xavp_t *cavu=0;
1360 	sr_xval_t rval;
1361 
1362 	cavu = xavp_new_value(name, val);
1363 	if (cavu==NULL) {
1364 		return NULL;
1365 	}
1366 
1367 	memset(&rval, 0, sizeof(sr_xval_t));
1368 	rval.type = SR_XTYPE_XAVP;
1369 	rval.v.xavp = cavu;
1370 
1371 	ravu = xavp_new_value(rname, &rval);
1372 	if (ravu==NULL) {
1373 		xavp_destroy_list(&cavu);
1374 		return NULL;
1375 	}
1376 
1377 	/* Prepend new value to the list */
1378 	if(list) {
1379 		ravu->next = *list;
1380 		*list = ravu;
1381 	} else {
1382 		ravu->next = *_xavu_list_crt;
1383 		*_xavu_list_crt = ravu;
1384 	}
1385 
1386 	return ravu;
1387 }
1388 
1389 /**
1390  * Set the value of the  xavu rname with child xavu cname
1391  * - set if it exits; add if it doesn't exist
1392  * - config operations:
1393  *   $xavu(rxname=>cname) = xval;
1394  */
xavu_set_child_xval(str * rname,str * cname,sr_xval_t * xval)1395 sr_xavp_t *xavu_set_child_xval(str *rname, str *cname, sr_xval_t *xval)
1396 {
1397 	sr_xavp_t *ravu=NULL;
1398 	sr_xavp_t *cavu=NULL;
1399 
1400 	ravu = xavu_get(rname, NULL);
1401 	if(ravu) {
1402 		if(ravu->val.type != SR_XTYPE_XAVP) {
1403 			/* first root xavp does not have xavp list value - remove it */
1404 			xavp_rm(ravu, NULL);
1405 			/* add a new xavp in the root list with a child */
1406 			return xavu_set_xavu_value(rname, cname, xval, NULL);
1407 		} else {
1408 			/* first root xavp has an xavp list value */
1409 			cavu = xavu_get(cname, ravu->val.v.xavp);
1410 			if(cavu) {
1411 				/* child xavp with same name - remove it */
1412 				/* todo: update in place for int or if allocated size fits */
1413 				xavp_rm(cavu, &ravu->val.v.xavp);
1414 			}
1415 			return xavp_add_value(cname, xval, &ravu->val.v.xavp);
1416 		}
1417 	} else {
1418 		/* no xavp with rname in root list found */
1419 		return xavu_set_xavu_value(rname, cname, xval, NULL);
1420 	}
1421 }
1422 
1423 /**
1424  *
1425  */
xavu_set_child_ival(str * rname,str * cname,int ival)1426 sr_xavp_t *xavu_set_child_ival(str *rname, str *cname, int ival)
1427 {
1428 	sr_xval_t xval;
1429 
1430 	memset(&xval, 0, sizeof(sr_xval_t));
1431 	xval.type = SR_XTYPE_INT;
1432 	xval.v.i = ival;
1433 
1434 	return xavu_set_child_xval(rname, cname, &xval);
1435 }
1436 
1437 /**
1438  *
1439  */
xavu_set_child_sval(str * rname,str * cname,str * sval)1440 sr_xavp_t *xavu_set_child_sval(str *rname, str *cname, str *sval)
1441 {
1442 	sr_xval_t xval;
1443 
1444 	memset(&xval, 0, sizeof(sr_xval_t));
1445 	xval.type = SR_XTYPE_STR;
1446 	xval.v.s = *sval;
1447 
1448 	return xavu_set_child_xval(rname, cname, &xval);
1449 }
1450 
1451 
1452 /**
1453  *
1454  */
1455 /*** XAVI - eXtended Attribute Value Insensitive case - implementation ***/
1456 /*! Helper functions */
1457 static sr_xavp_t *xavi_get_internal(str *name, sr_xavp_t **list, int idx, sr_xavp_t **prv);
1458 static int xavi_rm_internal(str *name, sr_xavp_t **head, int idx);
1459 
1460 /**
1461  *
1462  */
xavi_new_value(str * name,sr_xval_t * val)1463 static sr_xavp_t *xavi_new_value(str *name, sr_xval_t *val)
1464 {
1465 	sr_xavp_t *avi;
1466 	int size;
1467 	unsigned int id;
1468 
1469 	if(name==NULL || name->s==NULL || val==NULL)
1470 		return NULL;
1471 	id = get_hash1_case_raw(name->s, name->len);
1472 
1473 	size = sizeof(sr_xavp_t) + name->len + 1;
1474 	if(val->type == SR_XTYPE_STR)
1475 		size += val->v.s.len + 1;
1476 	avi = (sr_xavp_t*)shm_malloc(size);
1477 	if(avi==NULL) {
1478 		SHM_MEM_ERROR;
1479 		return NULL;
1480 	}
1481 	memset(avi, 0, size);
1482 	avi->id = id;
1483 	avi->name.s = (char*)avi + sizeof(sr_xavp_t);
1484 	memcpy(avi->name.s, name->s, name->len);
1485 	avi->name.s[name->len] = '\0';
1486 	avi->name.len = name->len;
1487 	memcpy(&avi->val, val, sizeof(sr_xval_t));
1488 	if(val->type == SR_XTYPE_STR)
1489 	{
1490 		avi->val.v.s.s = avi->name.s + avi->name.len + 1;
1491 		memcpy(avi->val.v.s.s, val->v.s.s, val->v.s.len);
1492 		avi->val.v.s.s[val->v.s.len] = '\0';
1493 		avi->val.v.s.len = val->v.s.len;
1494 	}
1495 
1496 	return avi;
1497 }
1498 
1499 /**
1500  *
1501  */
xavi_add(sr_xavp_t * xavi,sr_xavp_t ** list)1502 int xavi_add(sr_xavp_t *xavi, sr_xavp_t **list)
1503 {
1504 	if (xavi==NULL) {
1505 		return -1;
1506 	}
1507 	/* Prepend new xavi to the list */
1508 	if(list) {
1509 		xavi->next = *list;
1510 		*list = xavi;
1511 	} else {
1512 		xavi->next = *_xavi_list_crt;
1513 		*_xavi_list_crt = xavi;
1514 	}
1515 
1516 	return 0;
1517 }
1518 
1519 /**
1520  *
1521  */
xavi_add_last(sr_xavp_t * xavi,sr_xavp_t ** list)1522 int xavi_add_last(sr_xavp_t *xavi, sr_xavp_t **list)
1523 {
1524 	sr_xavp_t *prev;
1525 	sr_xavp_t *crt;
1526 
1527 	if (xavi==NULL) {
1528 		return -1;
1529 	}
1530 
1531 	crt = xavi_get_internal(&xavi->name, list, 0, 0);
1532 
1533 	prev = NULL;
1534 
1535 	while(crt) {
1536 		prev = crt;
1537 		crt = xavi_get_next(prev);
1538 	}
1539 
1540 	if(prev==NULL) {
1541 		/* Prepend new xavi to the list */
1542 		if(list) {
1543 			xavi->next = *list;
1544 			*list = xavi;
1545 		} else {
1546 			xavi->next = *_xavi_list_crt;
1547 			*_xavi_list_crt = xavi;
1548 		}
1549 	} else {
1550 		xavi->next = prev->next;
1551 		prev->next = xavi;
1552 	}
1553 
1554 	return 0;
1555 }
1556 
1557 /**
1558  *
1559  */
xavi_add_after(sr_xavp_t * nxavi,sr_xavp_t * pxavi)1560 int xavi_add_after(sr_xavp_t *nxavi, sr_xavp_t *pxavi)
1561 {
1562 	if (nxavi==NULL) {
1563 		return -1;
1564 	}
1565 
1566 	if(pxavi==NULL) {
1567 		nxavi->next = *_xavi_list_crt;
1568 		*_xavi_list_crt = nxavi;
1569 	} else {
1570 		nxavi->next = pxavi->next;
1571 		pxavi->next = nxavi;
1572 	}
1573 
1574 	return 0;
1575 }
1576 
1577 /**
1578  *
1579  */
xavi_add_value(str * name,sr_xval_t * val,sr_xavp_t ** list)1580 sr_xavp_t *xavi_add_value(str *name, sr_xval_t *val, sr_xavp_t **list)
1581 {
1582 	sr_xavp_t *avi=0;
1583 
1584 	avi = xavi_new_value(name, val);
1585 	if (avi==NULL)
1586 		return NULL;
1587 
1588 	/* Prepend new value to the list */
1589 	if(list) {
1590 		avi->next = *list;
1591 		*list = avi;
1592 	} else {
1593 		avi->next = *_xavi_list_crt;
1594 		*_xavi_list_crt = avi;
1595 	}
1596 
1597 	return avi;
1598 }
1599 
1600 /**
1601  *
1602  */
xavi_add_value_after(str * name,sr_xval_t * val,sr_xavp_t * pxavi)1603 sr_xavp_t *xavi_add_value_after(str *name, sr_xval_t *val, sr_xavp_t *pxavi)
1604 {
1605 	sr_xavp_t *avi=0;
1606 
1607 	avi = xavi_new_value(name, val);
1608 	if (avi==NULL)
1609 		return NULL;
1610 
1611 	/* link new xavi */
1612 	if(pxavi) {
1613 		avi->next = pxavi->next;
1614 		pxavi->next = avi;
1615 	} else {
1616 		avi->next = *_xavi_list_crt;
1617 		*_xavi_list_crt = avi;
1618 	}
1619 
1620 	return avi;
1621 }
1622 
1623 /**
1624  *
1625  */
xavi_add_xavi_value(str * rname,str * name,sr_xval_t * val,sr_xavp_t ** list)1626 sr_xavp_t *xavi_add_xavi_value(str *rname, str *name, sr_xval_t *val, sr_xavp_t **list)
1627 {
1628 	sr_xavp_t *ravi=0;
1629 	sr_xavp_t *cavi=0;
1630 	sr_xval_t rval;
1631 
1632 	cavi = xavi_new_value(name, val);
1633 	if (cavi==NULL)
1634 		return NULL;
1635 
1636 	memset(&rval, 0, sizeof(sr_xval_t));
1637 	rval.type = SR_XTYPE_XAVP;
1638 	rval.v.xavp = cavi;
1639 
1640 	ravi = xavi_new_value(rname, &rval);
1641 	if (ravi==NULL) {
1642 		xavi_destroy_list(&cavi);
1643 		return NULL;
1644 	}
1645 
1646 	/* Prepend new value to the list */
1647 	if(list) {
1648 		ravi->next = *list;
1649 		*list = ravi;
1650 	} else {
1651 		ravi->next = *_xavi_list_crt;
1652 		*_xavi_list_crt = ravi;
1653 	}
1654 
1655 	return ravi;
1656 }
1657 
1658 /**
1659  *
1660  */
xavi_set_value(str * name,int idx,sr_xval_t * val,sr_xavp_t ** list)1661 sr_xavp_t *xavi_set_value(str *name, int idx, sr_xval_t *val, sr_xavp_t **list)
1662 {
1663 	sr_xavp_t *avi;
1664 	sr_xavp_t *cur;
1665 	sr_xavp_t *prv=0;
1666 
1667 	if(val==NULL)
1668 		return NULL;
1669 
1670 	/* Find the current value */
1671 	cur = xavi_get_internal(name, list, idx, &prv);
1672 	if(cur==NULL)
1673 		return NULL;
1674 
1675 	avi = xavi_new_value(name, val);
1676 	if (avi==NULL)
1677 		return NULL;
1678 
1679 	/* Replace the current value with the new */
1680 	avi->next = cur->next;
1681 	if(prv)
1682 		prv->next = avi;
1683 	else if(list)
1684 		*list = avi;
1685 	else
1686 		*_xavi_list_crt = avi;
1687 
1688 	xavi_free(cur);
1689 
1690 	return avi;
1691 }
1692 
1693 /**
1694  *
1695  */
xavi_get_internal(str * name,sr_xavp_t ** list,int idx,sr_xavp_t ** prv)1696 static sr_xavp_t *xavi_get_internal(str *name, sr_xavp_t **list, int idx, sr_xavp_t **prv)
1697 {
1698 	sr_xavp_t *avi;
1699 	unsigned int id;
1700 	int n = 0;
1701 
1702 	if(name==NULL || name->s==NULL)
1703 		return NULL;
1704 	id = get_hash1_case_raw(name->s, name->len);
1705 
1706 	if(list && *list)
1707 		avi = *list;
1708 	else
1709 		avi = *_xavi_list_crt;
1710 	while(avi)
1711 	{
1712 		if(avi->id==id && avi->name.len==name->len
1713 				&& strncasecmp(avi->name.s, name->s, name->len)==0)
1714 		{
1715 			if(idx==n)
1716 				return avi;
1717 			n++;
1718 		}
1719 		if(prv)
1720 			*prv = avi;
1721 		avi = avi->next;
1722 	}
1723 	return NULL;
1724 }
1725 
1726 /**
1727  *
1728  */
xavi_get(str * name,sr_xavp_t * start)1729 sr_xavp_t *xavi_get(str *name, sr_xavp_t *start)
1730 {
1731 	return xavi_get_internal(name, (start)?&start:NULL, 0, NULL);
1732 }
1733 
1734 /**
1735  *
1736  */
xavi_get_by_index(str * name,int idx,sr_xavp_t ** start)1737 sr_xavp_t *xavi_get_by_index(str *name, int idx, sr_xavp_t **start)
1738 {
1739 	return xavi_get_internal(name, start, idx, NULL);
1740 }
1741 
1742 /**
1743  *
1744  */
xavi_get_next(sr_xavp_t * start)1745 sr_xavp_t *xavi_get_next(sr_xavp_t *start)
1746 {
1747 	sr_xavp_t *avi;
1748 
1749 	if(start==NULL)
1750 		return NULL;
1751 
1752 	avi = start->next;
1753 	while(avi)
1754 	{
1755 		if(avi->id==start->id && avi->name.len==start->name.len
1756 				&& strncasecmp(avi->name.s, start->name.s, start->name.len)==0)
1757 			return avi;
1758 		avi=avi->next;
1759 	}
1760 
1761 	return NULL;
1762 }
1763 
1764 /**
1765  *
1766  */
xavi_get_last(str * xname,sr_xavp_t ** list)1767 sr_xavp_t *xavi_get_last(str *xname, sr_xavp_t **list)
1768 {
1769 	sr_xavp_t *prev;
1770 	sr_xavp_t *crt;
1771 
1772 	crt = xavi_get_internal(xname, list, 0, 0);
1773 
1774 	prev = NULL;
1775 
1776 	while(crt) {
1777 		prev = crt;
1778 		crt = xavi_get_next(prev);
1779 	}
1780 
1781 	return prev;
1782 }
1783 
1784 /**
1785  *
1786  */
xavi_rm(sr_xavp_t * xa,sr_xavp_t ** head)1787 int xavi_rm(sr_xavp_t *xa, sr_xavp_t **head)
1788 {
1789 	sr_xavp_t *avi;
1790 	sr_xavp_t *prv=0;
1791 
1792 	if(head!=NULL)
1793 		avi = *head;
1794 	else
1795 		avi=*_xavi_list_crt;
1796 
1797 	while(avi)
1798 	{
1799 		if(avi==xa)
1800 		{
1801 			if(prv)
1802 				prv->next=avi->next;
1803 			else if(head!=NULL)
1804 				*head = avi->next;
1805 			else
1806 				*_xavi_list_crt = avi->next;
1807 			xavi_free(avi);
1808 			return 1;
1809 		}
1810 		prv=avi; avi=avi->next;
1811 	}
1812 	return 0;
1813 }
1814 
1815 /* Remove xavis
1816  * idx: <0 remove all xavis with the same name
1817  *      >=0 remove only the specified index xavi
1818  * Returns number of xavis that were deleted
1819  */
xavi_rm_internal(str * name,sr_xavp_t ** head,int idx)1820 static int xavi_rm_internal(str *name, sr_xavp_t **head, int idx)
1821 {
1822 	sr_xavp_t *avi;
1823 	sr_xavp_t *foo;
1824 	sr_xavp_t *prv=0;
1825 	unsigned int id;
1826 	int n=0;
1827 	int count=0;
1828 
1829 	if(name==NULL || name->s==NULL)
1830 		return 0;
1831 
1832 	id = get_hash1_case_raw(name->s, name->len);
1833 	if(head!=NULL)
1834 		avi = *head;
1835 	else
1836 		avi = *_xavi_list_crt;
1837 	while(avi)
1838 	{
1839 		foo = avi;
1840 		avi=avi->next;
1841 		if(foo->id==id && foo->name.len==name->len
1842 				&& strncasecmp(foo->name.s, name->s, name->len)==0)
1843 		{
1844 			if(idx<0 || idx==n)
1845 			{
1846 				if(prv!=NULL)
1847 					prv->next=foo->next;
1848 				else if(head!=NULL)
1849 					*head = foo->next;
1850 				else
1851 					*_xavi_list_crt = foo->next;
1852 				xavi_free(foo);
1853 				if(idx>=0)
1854 					return 1;
1855 				count++;
1856 			} else {
1857 				prv = foo;
1858 			}
1859 			n++;
1860 		} else {
1861 			prv = foo;
1862 		}
1863 	}
1864 	return count;
1865 }
1866 
1867 /**
1868  *
1869  */
xavi_rm_by_name(str * name,int all,sr_xavp_t ** head)1870 int xavi_rm_by_name(str *name, int all, sr_xavp_t **head)
1871 {
1872 	return xavi_rm_internal(name, head, -1*all);
1873 }
1874 
1875 /**
1876  *
1877  */
xavi_rm_by_index(str * name,int idx,sr_xavp_t ** head)1878 int xavi_rm_by_index(str *name, int idx, sr_xavp_t **head)
1879 {
1880 	if (idx<0)
1881 		return 0;
1882 	return xavi_rm_internal(name, head, idx);
1883 }
1884 
1885 /**
1886  *
1887  */
xavi_rm_child_by_index(str * rname,str * cname,int idx)1888 int xavi_rm_child_by_index(str *rname, str *cname, int idx)
1889 {
1890 	sr_xavp_t *avi=NULL;
1891 
1892 	if (idx<0) {
1893 		return 0;
1894 	}
1895 	avi = xavi_get(rname, NULL);
1896 
1897 	if(avi == NULL || avi->val.type!=SR_XTYPE_XAVP) {
1898 		return 0;
1899 	}
1900 	return xavi_rm_internal(cname, &avi->val.v.xavp, idx);
1901 }
1902 
1903 /**
1904  *
1905  */
xavi_count(str * name,sr_xavp_t ** start)1906 int xavi_count(str *name, sr_xavp_t **start)
1907 {
1908 	sr_xavp_t *avi;
1909 	unsigned int id;
1910 	int n = 0;
1911 
1912 	if(name==NULL || name->s==NULL)
1913 		return -1;
1914 	id = get_hash1_case_raw(name->s, name->len);
1915 
1916 	if(start)
1917 		avi = *start;
1918 	else
1919 		avi=*_xavi_list_crt;
1920 	while(avi)
1921 	{
1922 		if(avi->id==id && avi->name.len==name->len
1923 				&& strncasecmp(avi->name.s, name->s, name->len)==0)
1924 		{
1925 			n++;
1926 		}
1927 		avi=avi->next;
1928 	}
1929 
1930 	return n;
1931 }
1932 
1933 /**
1934  *
1935  */
xavi_reset_list(void)1936 void xavi_reset_list(void)
1937 {
1938 	assert(_xavi_list_crt!=0 );
1939 
1940 	if (_xavi_list_crt!=&_xavi_list_head)
1941 		_xavi_list_crt=&_xavi_list_head;
1942 	xavi_destroy_list(_xavi_list_crt);
1943 }
1944 
1945 /**
1946  *
1947  */
xavi_set_list(sr_xavp_t ** head)1948 sr_xavp_t **xavi_set_list(sr_xavp_t **head)
1949 {
1950 	sr_xavp_t **avi;
1951 
1952 	assert(_xavi_list_crt!=0);
1953 
1954 	avi = _xavi_list_crt;
1955 	_xavi_list_crt = head;
1956 	return avi;
1957 }
1958 
1959 /**
1960  *
1961  */
xavi_get_crt_list(void)1962 sr_xavp_t **xavi_get_crt_list(void)
1963 {
1964 	assert(_xavi_list_crt!=0);
1965 	return _xavi_list_crt;
1966 }
1967 
1968 /**
1969  *
1970  */
xavi_print_list_content(sr_xavp_t ** head,int level)1971 void xavi_print_list_content(sr_xavp_t **head, int level)
1972 {
1973 	xavx_print_list_content("XAVI", head, _xavi_list_crt, level);
1974 }
1975 
1976 /**
1977  *
1978  */
xavi_print_list(sr_xavp_t ** head)1979 void xavi_print_list(sr_xavp_t **head)
1980 {
1981 	xavi_print_list_content(head, 0);
1982 }
1983 
1984 /**
1985  * returns a list of str with key names.
1986  * Example:
1987  * If we have this structure
1988  * $xavi(test=>one) = 1
1989  * $xavi(test[0]=>two) = "2"
1990  * $xavi(test[0]=>three) = 3
1991  * $xavi(test[0]=>four) = $xavp(whatever)
1992  * $xavi(test[0]=>two) = "other 2"
1993  *
1994  * xavi_get_list_keys_names(test[0]) returns
1995  * {"one", "two", "three", "four"}
1996  *
1997  * free the struct str_list afterwards
1998  * but do *NOT* free the strings inside
1999  */
xavi_get_list_key_names(sr_xavp_t * xavi)2000 struct str_list *xavi_get_list_key_names(sr_xavp_t *xavi)
2001 {
2002 	sr_xavp_t *avi = NULL;
2003 	struct str_list *result = NULL;
2004 	struct str_list *r = NULL;
2005 	struct str_list *f = NULL;
2006 	int total = 0;
2007 
2008 	if(xavi==NULL){
2009 		LM_ERR("xavi is NULL\n");
2010 		return 0;
2011 	}
2012 
2013 	if(xavi->val.type!=SR_XTYPE_XAVP){
2014 		LM_ERR("%s not xavp?\n", xavi->name.s);
2015 		return 0;
2016 	}
2017 
2018 	avi = xavi->val.v.xavp;
2019 
2020 	if (avi)
2021 	{
2022 		result = (struct str_list*)pkg_malloc(sizeof(struct str_list));
2023 		if (result==NULL) {
2024 			PKG_MEM_ERROR;
2025 			return 0;
2026 		}
2027 		r = result;
2028 		r->s.s = avi->name.s;
2029 		r->s.len = avi->name.len;
2030 		r->next = NULL;
2031 		avi = avi->next;
2032 	}
2033 
2034 	while(avi)
2035 	{
2036 		f = result;
2037 		while(f)
2038 		{
2039 			if((avi->name.len==f->s.len)&&
2040 				(strncasecmp(avi->name.s, f->s.s, f->s.len)==0))
2041 			{
2042 				break; /* name already on list */
2043 			}
2044 			f = f->next;
2045 		}
2046 		if (f==NULL)
2047 		{
2048 			r = append_str_list(avi->name.s, avi->name.len, &r, &total);
2049 			if(r==NULL){
2050 				while(result){
2051 					r = result;
2052 					result = result->next;
2053 					pkg_free(r);
2054 				}
2055 				return 0;
2056 			}
2057 		}
2058 		avi = avi->next;
2059 	}
2060 	return result;
2061 }
2062 
xavi_clone_level_nodata(sr_xavp_t * xold)2063 sr_xavp_t *xavi_clone_level_nodata(sr_xavp_t *xold)
2064 {
2065 	return xavi_clone_level_nodata_with_new_name(xold, &xold->name);
2066 }
2067 
2068 /**
2069  * clone the xavi without values that are custom data
2070  * - only one list level is cloned, other sublists are ignored
2071  */
xavi_clone_level_nodata_with_new_name(sr_xavp_t * xold,str * dst_name)2072 sr_xavp_t *xavi_clone_level_nodata_with_new_name(sr_xavp_t *xold, str *dst_name)
2073 {
2074 	sr_xavp_t *xnew = NULL;
2075 	sr_xavp_t *navi = NULL;
2076 	sr_xavp_t *oavi = NULL;
2077 	sr_xavp_t *pavi = NULL;
2078 
2079 	if(xold == NULL)
2080 	{
2081 		return NULL;
2082 	}
2083 	if(xold->val.type==SR_XTYPE_DATA || xold->val.type==SR_XTYPE_SPTR)
2084 	{
2085 		LM_INFO("xavi value type is 'data' - ignoring in clone\n");
2086 		return NULL;
2087 	}
2088 	xnew = xavi_new_value(dst_name, &xold->val);
2089 	if(xnew==NULL)
2090 	{
2091 		LM_ERR("cannot create cloned root xavi\n");
2092 		return NULL;
2093 	}
2094 	LM_DBG("cloned root xavi [%.*s] >> [%.*s]\n", xold->name.len, xold->name.s, dst_name->len, dst_name->s);
2095 
2096 	if(xold->val.type!=SR_XTYPE_XAVP)
2097 	{
2098 		return xnew;
2099 	}
2100 
2101 	xnew->val.v.xavp = NULL;
2102 	oavi = xold->val.v.xavp;
2103 
2104 	while(oavi)
2105 	{
2106 		if(oavi->val.type!=SR_XTYPE_DATA && oavi->val.type!=SR_XTYPE_XAVP
2107 				&& oavi->val.type!=SR_XTYPE_SPTR)
2108 		{
2109 			navi =  xavi_new_value(&oavi->name, &oavi->val);
2110 			if(navi==NULL)
2111 			{
2112 				LM_ERR("cannot create cloned embedded xavi\n");
2113 				if(xnew->val.v.xavp != NULL) {
2114 					xavi_destroy_list(&xnew->val.v.xavp);
2115 				}
2116 				shm_free(xnew);
2117 				return NULL;
2118 			}
2119 			LM_DBG("cloned inner xavi [%.*s]\n", oavi->name.len, oavi->name.s);
2120 			if(xnew->val.v.xavp == NULL)
2121 			{
2122 				/* link to val in head xavi */
2123 				xnew->val.v.xavp = navi;
2124 			} else {
2125 				/* link to prev xavi in the list */
2126 				pavi->next = navi;
2127 			}
2128 			pavi = navi;
2129 		}
2130 		oavi = oavi->next;
2131 	}
2132 
2133 	if(xnew->val.v.xavp == NULL)
2134 	{
2135 		shm_free(xnew);
2136 		return NULL;
2137 	}
2138 
2139 	return xnew;
2140 }
2141 
xavi_insert(sr_xavp_t * xavi,int idx,sr_xavp_t ** list)2142 int xavi_insert(sr_xavp_t *xavi, int idx, sr_xavp_t **list)
2143 {
2144 	sr_xavp_t *crt = 0;
2145 	sr_xavp_t *lst = 0;
2146 	sr_xval_t val;
2147 	int n = 0;
2148 	int i = 0;
2149 
2150 	if(xavi==NULL) {
2151 		return -1;
2152 	}
2153 
2154 	crt = xavi_get_internal(&xavi->name, list, 0, NULL);
2155 
2156 	if (idx == 0 && (!crt || crt->val.type != SR_XTYPE_NULL))
2157 		return xavi_add(xavi, list);
2158 
2159 	while(crt!=NULL && n<idx) {
2160 		lst = crt;
2161 		n++;
2162 		crt = xavi_get_next(lst);
2163 	}
2164 
2165 	if (crt && crt->val.type == SR_XTYPE_NULL) {
2166 		xavi->next = crt->next;
2167 		crt->next = xavi;
2168 
2169 		xavi_rm(crt, list);
2170 		return 0;
2171 	}
2172 
2173 	memset(&val, 0, sizeof(sr_xval_t));
2174 	val.type = SR_XTYPE_NULL;
2175 	for(i=0; i<idx-n; i++) {
2176 		crt = xavi_new_value(&xavi->name, &val);
2177 		if(crt==NULL)
2178 			return -1;
2179 		if (lst == NULL) {
2180 			xavi_add(crt, list);
2181 		} else {
2182 			crt->next = lst->next;
2183 			lst->next = crt;
2184 		}
2185 		lst = crt;
2186 	}
2187 
2188 	if(lst==NULL) {
2189 		LM_ERR("cannot link the xavi\n");
2190 		return -1;
2191 	}
2192 	xavi->next = lst->next;
2193 	lst->next = xavi;
2194 
2195 	return 0;
2196 }
2197 
xavi_extract(str * name,sr_xavp_t ** list)2198 sr_xavp_t *xavi_extract(str *name, sr_xavp_t **list)
2199 {
2200 	sr_xavp_t *avi = 0;
2201 	sr_xavp_t *foo;
2202 	sr_xavp_t *prv = 0;
2203 	unsigned int id;
2204 
2205 	if(name==NULL || name->s==NULL) {
2206 		if(list!=NULL) {
2207 			avi = *list;
2208 			if(avi!=NULL) {
2209 				*list = avi->next;
2210 				avi->next = NULL;
2211 			}
2212 		} else {
2213 			avi = *_xavi_list_crt;
2214 			if(avi!=NULL) {
2215 				*_xavi_list_crt = avi->next;
2216 				avi->next = NULL;
2217 			}
2218 		}
2219 
2220 		return avi;
2221 	}
2222 
2223 	id = get_hash1_case_raw(name->s, name->len);
2224 	if(list!=NULL)
2225 		avi = *list;
2226 	else
2227 		avi = *_xavi_list_crt;
2228 	while(avi)
2229 	{
2230 		foo = avi;
2231 		avi=avi->next;
2232 		if(foo->id==id && foo->name.len==name->len
2233 				&& strncasecmp(foo->name.s, name->s, name->len)==0)
2234 		{
2235 			if(prv!=NULL)
2236 				prv->next=foo->next;
2237 			else if(list!=NULL)
2238 				*list = foo->next;
2239 			else
2240 				*_xavi_list_crt = foo->next;
2241 			foo->next = NULL;
2242 			return foo;
2243 		} else {
2244 			prv = foo;
2245 		}
2246 	}
2247 	return NULL;
2248 }
2249 
2250 /**
2251  * return child node of an xavi
2252  * - $xavi(rname=>cname)
2253  */
xavi_get_child(str * rname,str * cname)2254 sr_xavp_t* xavi_get_child(str *rname, str *cname)
2255 {
2256 	sr_xavp_t *ravi=NULL;
2257 
2258 	ravi = xavi_get(rname, NULL);
2259 	if(ravi==NULL || ravi->val.type!=SR_XTYPE_XAVP)
2260 		return NULL;
2261 
2262 	return xavi_get(cname, ravi->val.v.xavp);
2263 }
2264 
2265 
2266 /**
2267  * return child node of an xavi if it has int value
2268  * - $xavi(rname=>cname)
2269  */
xavi_get_child_with_ival(str * rname,str * cname)2270 sr_xavp_t* xavi_get_child_with_ival(str *rname, str *cname)
2271 {
2272 	sr_xavp_t *vavi=NULL;
2273 
2274 	vavi = xavi_get_child(rname, cname);
2275 
2276 	if(vavi==NULL || vavi->val.type!=SR_XTYPE_INT)
2277 		return NULL;
2278 
2279 	return vavi;
2280 }
2281 
2282 
2283 /**
2284  * return child node of an xavi if it has string value
2285  * - $xavi(rname=>cname)
2286  */
xavi_get_child_with_sval(str * rname,str * cname)2287 sr_xavp_t* xavi_get_child_with_sval(str *rname, str *cname)
2288 {
2289 	sr_xavp_t *vavi=NULL;
2290 
2291 	vavi = xavi_get_child(rname, cname);
2292 
2293 	if(vavi==NULL || vavi->val.type!=SR_XTYPE_STR)
2294 		return NULL;
2295 
2296 	return vavi;
2297 }
2298 
2299 /**
2300  * Set the value of the first xavi rname with first child xavi cname
2301  * - replace if it exits; add if it doesn't exist
2302  * - config operations:
2303  *   $xavi(rxname=>cname) = xval;
2304  *     or:
2305  *   $xavi(rxname[0]=>cname[0]) = xval;
2306  */
xavi_set_child_xval(str * rname,str * cname,sr_xval_t * xval)2307 int xavi_set_child_xval(str *rname, str *cname, sr_xval_t *xval)
2308 {
2309 	sr_xavp_t *ravi=NULL;
2310 	sr_xavp_t *cavi=NULL;
2311 
2312 	ravi = xavi_get(rname, NULL);
2313 	if(ravi) {
2314 		if(ravi->val.type != SR_XTYPE_XAVP) {
2315 			/* first root xavi does not have xavi list value - remove it */
2316 			xavi_rm(ravi, NULL);
2317 			/* add a new xavi in the root list with a child */
2318 			if(xavi_add_xavi_value(rname, cname, xval, NULL)==NULL) {
2319 				return -1;
2320 			}
2321 		} else {
2322 			/* first root xavi has an xavi list value */
2323 			cavi = xavi_get(cname, ravi->val.v.xavp);
2324 			if(cavi) {
2325 				/* child xavi with same name - remove it */
2326 				/* todo: update in place for int or if allocated size fits */
2327 				xavi_rm(cavi, &ravi->val.v.xavp);
2328 			}
2329 			if(xavi_add_value(cname, xval, &ravi->val.v.xavp)==NULL) {
2330 				return -1;
2331 			}
2332 		}
2333 	} else {
2334 		/* no xavi with rname in root list found */
2335 		if(xavi_add_xavi_value(rname, cname, xval, NULL)==NULL) {
2336 			return -1;
2337 		}
2338 	}
2339 
2340 	return 0;
2341 }
2342 
2343 /**
2344  *
2345  */
xavi_set_child_ival(str * rname,str * cname,int ival)2346 int xavi_set_child_ival(str *rname, str *cname, int ival)
2347 {
2348 	sr_xval_t xval;
2349 
2350 	memset(&xval, 0, sizeof(sr_xval_t));
2351 	xval.type = SR_XTYPE_INT;
2352 	xval.v.i = ival;
2353 
2354 	return xavi_set_child_xval(rname, cname, &xval);
2355 }
2356 
2357 /**
2358  *
2359  */
xavi_set_child_sval(str * rname,str * cname,str * sval)2360 int xavi_set_child_sval(str *rname, str *cname, str *sval)
2361 {
2362 	sr_xval_t xval;
2363 
2364 	memset(&xval, 0, sizeof(sr_xval_t));
2365 	xval.type = SR_XTYPE_STR;
2366 	xval.v.s = *sval;
2367 
2368 	return xavi_set_child_xval(rname, cname, &xval);
2369 }
2370 
2371 /**
2372  * serialize the values in subfields of an xavi in name=value; format
2373  * - rname - name of the root list xavi
2374  * - obuf - buffer were to write the output
2375  * - olen - the size of obuf
2376  * return: 0 - not found; -1 - error; >0 - length of output
2377  */
xavi_serialize_fields(str * rname,char * obuf,int olen)2378 int xavi_serialize_fields(str *rname, char *obuf, int olen)
2379 {
2380 	sr_xavp_t *ravi = NULL;
2381 	sr_xavp_t *avi = NULL;
2382 	str ostr;
2383 	int rlen;
2384 
2385 	ravi = xavi_get(rname, NULL);
2386 	if(ravi==NULL || ravi->val.type!=SR_XTYPE_XAVP) {
2387 		/* not found or not holding subfields */
2388 		return 0;
2389 	}
2390 
2391 	rlen = 0;
2392 	ostr.s = obuf;
2393 	avi = ravi->val.v.xavp;
2394 	while(avi) {
2395 		switch(avi->val.type) {
2396 			case SR_XTYPE_INT:
2397 				LM_DBG("     XAVP int value: %d\n", avi->val.v.i);
2398 				ostr.len = snprintf(ostr.s, olen-rlen, "%.*s=%u;",
2399 						avi->name.len, avi->name.s, (unsigned int)avi->val.v.i);
2400 				if(ostr.len<=0 || ostr.len>=olen-rlen) {
2401 					LM_ERR("failed to serialize int value (%d/%d\n",
2402 							ostr.len, olen-rlen);
2403 					return -1;
2404 				}
2405 			break;
2406 			case SR_XTYPE_STR:
2407 				LM_DBG("     XAVP str value: %s\n", avi->val.v.s.s);
2408 				if(avi->val.v.s.len == 0) {
2409 					ostr.len = snprintf(ostr.s, olen-rlen, "%.*s;",
2410 						avi->name.len, avi->name.s);
2411 				} else {
2412 					ostr.len = snprintf(ostr.s, olen-rlen, "%.*s=%.*s;",
2413 						avi->name.len, avi->name.s,
2414 						avi->val.v.s.len, avi->val.v.s.s);
2415 				}
2416 				if(ostr.len<=0 || ostr.len>=olen-rlen) {
2417 					LM_ERR("failed to serialize int value (%d/%d\n",
2418 							ostr.len, olen-rlen);
2419 					return -1;
2420 				}
2421 			break;
2422 			default:
2423 				LM_DBG("skipping value type: %d\n", avi->val.type);
2424 				ostr.len = 0;
2425 		}
2426 		if(ostr.len>0) {
2427 			ostr.s += ostr.len;
2428 			rlen += ostr.len;
2429 		}
2430 		avi = avi->next;
2431 	}
2432 	return rlen;
2433 }
2434