Merge remote branch 'origin/andrei/pointer_alias_warnings'
[sip-router] / usr_avp.c
1 /*
2  * $Id$
3  *
4  * Copyright (C) 2001-2003 FhG Fokus
5  *
6  * This file is part of ser, a free SIP server.
7  *
8  * ser is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version
12  *
13  * For a license to use the ser software under conditions
14  * other than those described here, or to purchase support for this
15  * software, please contact iptel.org by e-mail at the following addresses:
16  *    info@iptel.org
17  *
18  * ser is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26  *
27  * History:
28  * ---------
29  *  2004-07-21  created (bogdan)
30  *  2004-10-09  interface more flexible - more function available (bogdan)
31  *  2004-11-07  AVP string values are kept 0 terminated (bogdan)
32  *  2004-11-14  global aliases support added
33  *  2005-01-05  parse avp name according new syntax
34  */
35
36
37 /*!
38  * \file
39  * \brief SIP-router core :: 
40  * \ingroup core
41  * Module: \ref core
42  */
43
44 #include <assert.h>
45 #include <ctype.h>
46 #include <string.h>
47 #include <stdlib.h>
48
49 #include <stdio.h>
50
51 #include "sr_module.h"
52 #include "dprint.h"
53 #include "str.h"
54 #include "ut.h"
55 #include "mem/shm_mem.h"
56 #include "mem/mem.h"
57 #include "usr_avp.h"
58
59 enum idx {
60         IDX_FROM_URI = 0,
61         IDX_TO_URI,
62         IDX_FROM_USER,
63         IDX_TO_USER,
64         IDX_FROM_DOMAIN,
65         IDX_TO_DOMAIN,
66         IDX_MAX
67 };
68
69
70 struct avp_galias {
71         str alias;
72         struct avp_spec  avp;
73         struct avp_galias *next;
74 };
75
76 static struct avp_galias *galiases = 0;
77
78 static avp_list_t def_list[IDX_MAX];    /* Default AVP lists */
79 static avp_list_t* crt_list[IDX_MAX];  /* Pointer to current AVP lists */
80
81 /* Global AVP related variables go to shm mem */
82 static avp_list_t* def_glist;
83 static avp_list_t** crt_glist;
84
85 /* AVP flags */
86 int registered_avpflags_no = 0;
87 static char *registered_avpflags[MAX_AVPFLAG];
88
89 /* Initialize AVP lists in private memory and allocate memory
90  * for shared lists
91  */
92 int init_avps(void)
93 {
94         int i;
95              /* Empty default lists */
96         memset(def_list, 0, sizeof(avp_list_t) * IDX_MAX);
97
98              /* Point current pointers to default lists */
99         for(i = 0; i < IDX_MAX; i++) {
100                 crt_list[i] = &def_list[i];
101         }
102
103         def_glist = (avp_list_t*)shm_malloc(sizeof(avp_list_t));
104         crt_glist = (avp_list_t**)shm_malloc(sizeof(avp_list_t*));
105         if (!def_glist || !crt_glist) {
106                 LOG(L_ERR, "ERROR: No memory to allocate default global AVP list\n");
107                 return -1;
108         }
109         *def_glist = 0;
110         *crt_glist = def_glist;
111         return 0;
112 }
113
114
115 /*
116  * Select active AVP list based on the value of flags
117  */
118 static avp_list_t* select_list(avp_flags_t flags)
119 {
120         if (flags & AVP_CLASS_URI) {
121                 if (flags & AVP_TRACK_TO) {
122                         return crt_list[IDX_TO_URI];
123                 } else {
124                         return crt_list[IDX_FROM_URI];
125                 }
126         } else if (flags & AVP_CLASS_USER) {
127                 if (flags & AVP_TRACK_TO) {
128                         return crt_list[IDX_TO_USER];
129                 } else {
130                         return crt_list[IDX_FROM_USER];
131                 }
132         } else if (flags & AVP_CLASS_DOMAIN) {
133                 if (flags & AVP_TRACK_TO) {
134                         return crt_list[IDX_TO_DOMAIN];
135                 } else {
136                         return crt_list[IDX_FROM_DOMAIN];
137                 }
138         } else if (flags & AVP_CLASS_GLOBAL) {
139                 return *crt_glist;
140         }
141
142         return NULL;
143 }
144
145 inline static avp_id_t compute_ID( str *name )
146 {
147         char *p;
148         avp_id_t id;
149
150         id=0;
151         for( p=name->s+name->len-1 ; p>=name->s ; p-- )
152                 id ^= *p;
153         return id;
154 }
155
156
157 avp_t *create_avp (avp_flags_t flags, avp_name_t name, avp_value_t val)
158 {
159         avp_t *avp;
160         str *s;
161         struct str_int_data *sid;
162         struct str_str_data *ssd;
163         int len;
164
165         if (name.s.s == 0 && name.s.len == 0) {
166                 LOG(L_ERR,"ERROR:avp:add_avp: 0 ID or NULL NAME AVP!");
167                 goto error;
168         }
169
170         /* compute the required mem size */
171         len = sizeof(struct usr_avp);
172         if (flags&AVP_NAME_STR) {
173                 if ( name.s.s==0 || name.s.len==0) {
174                         LOG(L_ERR,"ERROR:avp:add_avp: EMPTY NAME AVP!");
175                         goto error;
176                 }
177                 if (flags&AVP_VAL_STR) {
178                         len += sizeof(struct str_str_data)-sizeof(union usr_avp_data)
179                                 + name.s.len + 1 /* Terminating zero for regex search */
180                                 + val.s.len + 1; /* Value is zero terminated */
181                 } else {
182                         len += sizeof(struct str_int_data)-sizeof(union usr_avp_data)
183                                 + name.s.len + 1; /* Terminating zero for regex search */
184                 }
185         } else if (flags&AVP_VAL_STR) {
186                 len += sizeof(str)-sizeof(union usr_avp_data) + val.s.len + 1;
187         }
188
189         avp = (struct usr_avp*)shm_malloc( len );
190         if (avp==0) {
191                 LOG(L_ERR,"ERROR:avp:add_avp: no more shm mem\n");
192                 return 0;
193         }
194
195         avp->flags = flags;
196         avp->id = (flags&AVP_NAME_STR)? compute_ID(&name.s) : name.n ;
197         avp->next = NULL;
198
199         switch ( flags&(AVP_NAME_STR|AVP_VAL_STR) )
200         {
201                 case 0:
202                         /* avp type ID, int value */
203                         avp->d.l = val.n;
204                         break;
205                 case AVP_NAME_STR:
206                         /* avp type str, int value */
207                         sid = (struct str_int_data*)&avp->d.data[0];
208                         sid->val = val.n;
209                         sid->name.len =name.s.len;
210                         sid->name.s = (char*)sid + sizeof(struct str_int_data);
211                         memcpy( sid->name.s , name.s.s, name.s.len);
212                         sid->name.s[name.s.len] = '\0'; /* Zero terminator */
213                         break;
214                 case AVP_VAL_STR:
215                         /* avp type ID, str value */
216                         s = (str*)&avp->d.data[0];
217                         s->len = val.s.len;
218                         s->s = (char*)s + sizeof(str);
219                         memcpy( s->s, val.s.s , s->len);
220                         s->s[s->len] = 0;
221                         break;
222                 case AVP_NAME_STR|AVP_VAL_STR:
223                         /* avp type str, str value */
224                         ssd = (struct str_str_data*)&avp->d.data[0];
225                         ssd->name.len = name.s.len;
226                         ssd->name.s = (char*)ssd + sizeof(struct str_str_data);
227                         memcpy( ssd->name.s , name.s.s, name.s.len);
228                         ssd->name.s[name.s.len]='\0'; /* Zero terminator */
229                         ssd->val.len = val.s.len;
230                         ssd->val.s = ssd->name.s + ssd->name.len + 1;
231                         memcpy( ssd->val.s , val.s.s, val.s.len);
232                         ssd->val.s[ssd->val.len] = 0;
233                         break;
234         }
235         return avp;
236 error:
237         return 0;
238 }
239
240 int add_avp_list(avp_list_t* list, avp_flags_t flags, avp_name_t name, avp_value_t val)
241 {
242         avp_t *avp;
243
244         assert(list != 0);
245
246         if ((avp = create_avp(flags, name, val))) {
247                 avp->next = *list;
248                 *list = avp;
249                 return 0;
250         }
251
252         return -1;
253 }
254
255
256 int add_avp(avp_flags_t flags, avp_name_t name, avp_value_t val)
257 {
258         avp_flags_t avp_class;
259         avp_list_t* list;
260
261              /* Add avp to uri class if no class has been
262               * specified by the caller
263               */
264         if ((flags & AVP_CLASS_ALL) == 0) flags |= AVP_CLASS_URI;
265         if ((flags & AVP_TRACK_ALL) == 0) flags |= AVP_TRACK_FROM;
266         if (!(list = select_list(flags)))
267                 return -1;
268
269         if (flags & AVP_CLASS_URI) avp_class = AVP_CLASS_URI;
270         else if (flags & AVP_CLASS_USER) avp_class = AVP_CLASS_USER;
271         else if (flags & AVP_CLASS_DOMAIN) avp_class = AVP_CLASS_DOMAIN;
272         else avp_class = AVP_CLASS_GLOBAL;
273
274              /* Make that only the selected class is set
275               * if the caller set more classes in flags
276               */
277         return add_avp_list(list, flags & (~(AVP_CLASS_ALL) | avp_class), name, val);
278 }
279
280 int add_avp_before(avp_t *avp, avp_flags_t flags, avp_name_t name, avp_value_t val)
281 {
282         avp_t *new_avp;
283
284         if (!avp) {
285                 return add_avp(flags, name, val);
286         }
287
288         if ((flags & AVP_CLASS_ALL) == 0) flags |= (avp->flags & AVP_CLASS_ALL);
289         if ((flags & AVP_TRACK_ALL) == 0) flags |= (avp->flags & AVP_TRACK_ALL);
290
291         if ((avp->flags & (AVP_CLASS_ALL|AVP_TRACK_ALL)) != (flags & (AVP_CLASS_ALL|AVP_TRACK_ALL))) {
292                 ERR("add_avp_before:Source and target AVPs have different CLASS/TRACK\n");
293                 return -1;
294         }
295         if ((new_avp=create_avp(flags, name, val))) {
296                 new_avp->next=avp->next;
297                 avp->next=new_avp;
298                 return 0;
299         }
300         return -1;
301 }
302
303 /* get value functions */
304 inline str* get_avp_name(avp_t *avp)
305 {
306         struct str_int_data *sid;
307         struct str_str_data *ssd;
308         
309         switch ( avp->flags&(AVP_NAME_STR|AVP_VAL_STR) )
310         {
311                 case 0:
312                         /* avp type ID, int value */
313                 case AVP_VAL_STR:
314                         /* avp type ID, str value */
315                         return 0;
316                 case AVP_NAME_STR:
317                         /* avp type str, int value */
318                         sid = (struct str_int_data*)&avp->d.data[0];
319                         return &sid->name;
320                 case AVP_NAME_STR|AVP_VAL_STR:
321                         /* avp type str, str value */
322                         ssd = (struct str_str_data*)&avp->d.data[0];
323                         return &ssd->name;
324         }
325
326         LOG(L_ERR,"BUG:avp:get_avp_name: unknown avp type (name&val) %d\n",
327             avp->flags&(AVP_NAME_STR|AVP_VAL_STR));
328         return 0;
329 }
330
331
332 inline void get_avp_val(avp_t *avp, avp_value_t *val)
333 {
334         str *s;
335         struct str_int_data *sid;
336         struct str_str_data *ssd;
337         
338         if (avp==0 || val==0)
339                 return;
340
341         switch ( avp->flags&(AVP_NAME_STR|AVP_VAL_STR) ) {
342                 case 0:
343                         /* avp type ID, int value */
344                         val->n = avp->d.l;
345                         break;
346                 case AVP_NAME_STR:
347                         /* avp type str, int value */
348                         sid = (struct str_int_data*)&avp->d.data[0];
349                         val->n = sid->val;
350                         break;
351                 case AVP_VAL_STR:
352                         /* avp type ID, str value */
353                         s = (str*)&avp->d.data[0];
354                         val->s = *s;
355                         break;
356                 case AVP_NAME_STR|AVP_VAL_STR:
357                         /* avp type str, str value */
358                         ssd = (struct str_str_data*)&avp->d.data[0];
359                         val->s = ssd->val;
360                         break;
361         }
362 }
363
364
365 /* Return the current list of user attributes */
366 avp_list_t get_avp_list(avp_flags_t flags)
367 {
368         avp_list_t *list;
369
370         list = select_list(flags);
371         return (list ? *list : NULL);
372 }
373
374
375 /*
376  * Compare given id with id in avp, return true if they match
377  */
378 static inline int match_by_id(avp_t* avp, avp_id_t id)
379 {
380         if (avp->id == id && (avp->flags&AVP_NAME_STR)==0) {
381                 return 1;
382         }
383         return 0;
384 }
385
386
387 /*
388  * Compare given name with name in avp, return true if they are same
389  */
390 static inline int match_by_name(avp_t* avp, avp_id_t id, str* name)
391 {
392         str* avp_name;
393         if (id==avp->id && avp->flags&AVP_NAME_STR &&
394             (avp_name=get_avp_name(avp))!=0 && avp_name->len==name->len
395             && !strncasecmp( avp_name->s, name->s, name->len) ) {
396                 return 1;
397         }
398         return 0;
399 }
400
401
402 /*
403  * Compare name with name in AVP using regular expressions, return
404  * true if they match
405  */
406 static inline int match_by_re(avp_t* avp, regex_t* re)
407 {
408         regmatch_t pmatch;
409         str * avp_name;
410              /* AVP identifiable by name ? */
411         if (!(avp->flags&AVP_NAME_STR)) return 0;
412         if ((avp_name=get_avp_name(avp))==0) /* valid AVP name ? */
413                 return 0;
414         if (!avp_name->s) /* AVP name validation */
415                 return 0;
416         if (regexec(re, avp_name->s, 1, &pmatch,0)==0) { /* re match ? */
417                 return 1;
418         }
419         return 0;
420 }
421
422
423 avp_t *search_first_avp(avp_flags_t flags, avp_name_t name, avp_value_t *val, struct search_state* s)
424 {
425         avp_ident_t id;
426         id.flags = flags;
427         id.name = name;
428         id.index = 0;
429         return search_avp (id, val, s);
430 }
431
432 avp_t *search_avp (avp_ident_t ident, avp_value_t* val, struct search_state* state)
433 {
434         avp_t* ret;
435         static struct search_state st;
436         avp_list_t* list;
437
438         if (ident.name.s.s==0 && ident.name.s.len == 0) {
439                 LOG(L_ERR,"ERROR:avp:search_first_avp: 0 ID or NULL NAME AVP!");
440                 return 0;
441         }
442
443         switch (ident.flags & AVP_INDEX_ALL) {
444                 case AVP_INDEX_BACKWARD:
445                 case AVP_INDEX_FORWARD:
446                         WARN("AVP specified with index, but not used for search\n");
447                         break;
448         }
449
450         if (!state) state = &st;
451
452         if ((ident.flags & AVP_CLASS_ALL) == 0) {
453                      /* The caller did not specify any class to search in, so enable
454                       * all of them by default
455                       */
456                 ident.flags |= AVP_CLASS_ALL;
457
458                 if ((ident.flags & AVP_TRACK_ALL) == 0) {
459                     /* The caller did not specify even the track to search in, so search
460                      * in the track_from
461                      */
462                         ident.flags |= AVP_TRACK_FROM;
463                 }
464         }
465
466         if (!(list = select_list(ident.flags)))
467                 return NULL;
468
469         state->flags = ident.flags;
470         state->avp = *list;
471         state->name = ident.name;
472
473         if (ident.flags & AVP_NAME_STR) {
474                 state->id = compute_ID(&ident.name.s);
475         }
476
477         ret = search_next_avp(state, val);
478
479              /* Make sure that search next avp stays in the same class as the first
480               * avp found
481               */
482         if (state && ret) state->flags = (ident.flags & ~AVP_CLASS_ALL) | (ret->flags & AVP_CLASS_ALL);
483         return ret;
484 }
485
486 avp_t *search_next_avp(struct search_state* s, avp_value_t *val )
487 {
488         int matched;
489         avp_t* avp;
490         avp_list_t *list;
491
492         if (s == 0) {
493                 LOG(L_ERR, "search_next:avp: Invalid parameter value\n");
494                 return 0;
495         }
496
497         switch (s->flags & AVP_INDEX_ALL) {
498                 case AVP_INDEX_BACKWARD:
499                 case AVP_INDEX_FORWARD:
500                         WARN("AVP specified with index, but not used for search\n");
501                         break;
502         }
503
504         while(1) {
505                 for( ; s->avp; s->avp = s->avp->next) {
506                         if (s->flags & AVP_NAME_RE) {
507                                 matched = match_by_re(s->avp, s->name.re);
508                         } else if (s->flags & AVP_NAME_STR) {
509                                 matched = match_by_name(s->avp, s->id, &s->name.s);
510                         } else {
511                                 matched = match_by_id(s->avp, s->name.n);
512                         }
513                         if (matched) {
514                                 avp = s->avp;
515                                 s->avp = s->avp->next;
516                                 if (val) get_avp_val(avp, val);
517                                 return avp;
518                         }
519                 }
520
521                 if (s->flags & AVP_CLASS_URI) {
522                         s->flags &= ~AVP_CLASS_URI;
523                         list = select_list(s->flags);
524                 } else if (s->flags & AVP_CLASS_USER) {
525                         s->flags &= ~AVP_CLASS_USER;
526                         list = select_list(s->flags);
527                 } else if (s->flags & AVP_CLASS_DOMAIN) {
528                         s->flags &= ~AVP_CLASS_DOMAIN;
529                         list = select_list(s->flags);
530                 } else {
531                         s->flags &= ~AVP_CLASS_GLOBAL;
532                         return 0;
533                 }
534                 if (!list) return 0;
535                 s->avp = *list;
536         }
537
538         return 0;
539 }
540
541 int search_reverse( avp_t *cur, struct search_state* st,
542                      avp_index_t index, avp_list_t *ret)
543 {
544         avp_index_t lvl;
545
546         if (!cur)
547                 return 0;
548         lvl = search_reverse(search_next_avp(st, NULL), st, index, ret)+1;
549         if (index==lvl)
550                 *ret=cur;
551         return lvl;
552 }
553
554 avp_t *search_avp_by_index( avp_flags_t flags, avp_name_t name,
555                             avp_value_t *val, avp_index_t index)
556 {
557         avp_t *ret, *cur;
558         struct search_state st;
559
560         if (flags & AVP_NAME_RE) {
561                 BUG("search_by_index not supported for AVP_NAME_RE\n");
562                 return 0;
563         }
564         switch (flags & AVP_INDEX_ALL) {
565                 case 0:
566                         ret = search_first_avp(flags, name, val, &st);
567                         if (!ret || search_next_avp(&st, NULL))
568                                 return 0;
569                         else
570                                 return ret;
571                 case AVP_INDEX_ALL:
572                         BUG("search_by_index not supported for anonymous index []\n");
573                         return 0;
574                 case AVP_INDEX_FORWARD:
575                         ret = NULL;
576                         cur = search_first_avp(flags & ~AVP_INDEX_ALL, name, NULL, &st);
577                         search_reverse(cur, &st, index, &ret);
578                         if (ret && val)
579                                 get_avp_val(ret, val);
580                         return ret;
581                 case AVP_INDEX_BACKWARD:
582                         ret = search_first_avp(flags & ~AVP_INDEX_ALL, name, val, &st);
583                         for (index--; (ret && index); ret=search_next_avp(&st, val), index--);
584                         return ret;
585         }
586
587         return 0;
588 }
589
590 /* FIXME */
591 /********* free functions ********/
592
593 void destroy_avp(avp_t *avp_del)
594 {
595         int i;
596         avp_t *avp, *avp_prev;
597
598         for (i = 0; i < IDX_MAX; i++) {
599                 for( avp_prev=0,avp=*crt_list[i] ; avp ;
600                      avp_prev=avp,avp=avp->next ) {
601                         if (avp==avp_del) {
602                                 if (avp_prev) {
603                                         avp_prev->next=avp->next;
604                                 } else {
605                                         *crt_list[i] = avp->next;
606                                 }
607                                 shm_free(avp);
608                                 return;
609                         }
610                 }
611         }
612
613         for( avp_prev=0,avp=**crt_glist ; avp ;
614              avp_prev=avp,avp=avp->next ) {
615                 if (avp==avp_del) {
616                         if (avp_prev) {
617                                 avp_prev->next=avp->next;
618                         } else {
619                                 **crt_glist = avp->next;
620                         }
621                         shm_free(avp);
622                         return;
623                 }
624         }
625 }
626
627
628 void destroy_avp_list_unsafe(avp_list_t* list)
629 {
630         avp_t *avp, *foo;
631
632         avp = *list;
633         while( avp ) {
634                 foo = avp;
635                 avp = avp->next;
636                 shm_free_unsafe( foo );
637         }
638         *list = 0;
639 }
640
641
642 inline void destroy_avp_list(avp_list_t* list)
643 {
644         avp_t *avp, *foo;
645
646         DBG("DEBUG:destroy_avp_list: destroying list %p\n", *list);
647         avp = *list;
648         while( avp ) {
649                 foo = avp;
650                 avp = avp->next;
651                 shm_free( foo );
652         }
653         *list = 0;
654 }
655
656 int reset_avp_list(int flags)
657 {
658     int i;
659     if (flags & AVP_CLASS_URI) {
660         if (flags & AVP_TRACK_FROM) i = IDX_FROM_URI;
661         else i = IDX_TO_URI;
662     } else if (flags & AVP_CLASS_USER) {
663         if (flags & AVP_TRACK_FROM) i = IDX_FROM_USER;
664         else i = IDX_TO_USER;
665     } else if (flags & AVP_CLASS_DOMAIN) {
666         if (flags & AVP_TRACK_FROM) i = IDX_FROM_DOMAIN;
667         else i = IDX_TO_DOMAIN;
668     } else return -1;
669
670     crt_list[i] = &def_list[i];
671     destroy_avp_list(crt_list[i]);
672     return 0;
673 }
674
675 void reset_avps(void)
676 {
677         int i;
678         for(i = 0; i < IDX_MAX; i++) {
679                 crt_list[i] = &def_list[i];
680                 destroy_avp_list(crt_list[i]);
681         }
682 }
683
684
685 avp_list_t* set_avp_list( avp_flags_t flags, avp_list_t* list )
686 {
687         avp_list_t* prev;
688
689         if (flags & AVP_CLASS_URI) {
690                 if (flags & AVP_TRACK_FROM) {
691                         prev = crt_list[IDX_FROM_URI];
692                         crt_list[IDX_FROM_URI] = list;
693                 } else {
694                         prev = crt_list[IDX_TO_URI];
695                         crt_list[IDX_TO_URI] = list;
696                 }
697         } else if (flags & AVP_CLASS_USER) {
698                 if (flags & AVP_TRACK_FROM) {
699                         prev = crt_list[IDX_FROM_USER];
700                         crt_list[IDX_FROM_USER] = list;
701                 } else {
702                         prev = crt_list[IDX_TO_USER];
703                         crt_list[IDX_TO_USER] = list;
704                 }
705         } else if (flags & AVP_CLASS_DOMAIN) {
706                 if (flags & AVP_TRACK_FROM) {
707                         prev = crt_list[IDX_FROM_DOMAIN];
708                         crt_list[IDX_FROM_DOMAIN] = list;
709                 } else {
710                         prev = crt_list[IDX_TO_DOMAIN];
711                         crt_list[IDX_TO_DOMAIN] = list;
712                 }
713         } else {
714                 prev = *crt_glist;
715                 *crt_glist = list;
716         }
717
718         return prev;
719 }
720
721
722 /********* global aliases functions ********/
723
724 static inline int check_avp_galias(str *alias, int type, int_str avp_name)
725 {
726         struct avp_galias *ga;
727
728         type &= AVP_NAME_STR;
729
730         for( ga=galiases ; ga ; ga=ga->next ) {
731                 /* check for duplicated alias names */
732                 if ( alias->len==ga->alias.len &&
733                 (strncasecmp( alias->s, ga->alias.s, alias->len)==0) )
734                         return -1;
735                 /*check for duplicated avp names */
736                 if (type==ga->avp.type) {
737                         if (type&AVP_NAME_STR){
738                                 if (avp_name.s.len==ga->avp.name.s.len &&
739                                     (strncasecmp(avp_name.s.s, ga->avp.name.s.s,
740                                                  avp_name.s.len)==0) )
741                                         return -1;
742                         } else {
743                                 if (avp_name.n==ga->avp.name.n)
744                                         return -1;
745                         }
746                 }
747         }
748         return 0;
749 }
750
751
752 int add_avp_galias(str *alias, int type, int_str avp_name)
753 {
754         struct avp_galias *ga;
755
756         if ((type&AVP_NAME_STR && (!avp_name.s.s ||
757                                    !avp_name.s.len)) ||!alias || !alias->s ||
758                 !alias->len ){
759                 LOG(L_ERR, "ERROR:add_avp_galias: null params received\n");
760                 goto error;
761         }
762
763         if (check_avp_galias(alias,type,avp_name)!=0) {
764                 LOG(L_ERR, "ERROR:add_avp_galias: duplicate alias/avp entry\n");
765                 goto error;
766         }
767
768         ga = (struct avp_galias*)pkg_malloc( sizeof(struct avp_galias) );
769         if (ga==0) {
770                 LOG(L_ERR, "ERROR:add_avp_galias: no more pkg memory\n");
771                 goto error;
772         }
773
774         ga->alias.s = (char*)pkg_malloc( alias->len+1 );
775         if (ga->alias.s==0) {
776                 LOG(L_ERR, "ERROR:add_avp_galias: no more pkg memory\n");
777                 goto error1;
778         }
779         memcpy( ga->alias.s, alias->s, alias->len);
780         ga->alias.len = alias->len;
781
782         ga->avp.type = type&AVP_NAME_STR;
783
784         if (type&AVP_NAME_STR) {
785                 ga->avp.name.s.s = (char*)pkg_malloc( avp_name.s.len+1 );
786                 if (ga->avp.name.s.s==0) {
787                         LOG(L_ERR, "ERROR:add_avp_galias: no more pkg memory\n");
788                         goto error2;
789                 }
790                 ga->avp.name.s.len = avp_name.s.len;
791                 memcpy( ga->avp.name.s.s, avp_name.s.s, avp_name.s.len);
792                 ga->avp.name.s.s[avp_name.s.len] = 0;
793                 DBG("DEBUG:add_avp_galias: registering <%s> for avp name <%s>\n",
794                         ga->alias.s, ga->avp.name.s.s);
795         } else {
796                 ga->avp.name.n = avp_name.n;
797                 DBG("DEBUG:add_avp_galias: registering <%s> for avp id <%d>\n",
798                         ga->alias.s, ga->avp.name.n);
799         }
800
801         ga->next = galiases;
802         galiases = ga;
803
804         return 0;
805 error2:
806         pkg_free(ga->alias.s);
807 error1:
808         pkg_free(ga);
809 error:
810         return -1;
811 }
812
813
814 int lookup_avp_galias(str *alias, int *type, int_str *avp_name)
815 {
816         struct avp_galias *ga;
817
818         for( ga=galiases ; ga ; ga=ga->next )
819                 if (alias->len==ga->alias.len &&
820                 (strncasecmp( alias->s, ga->alias.s, alias->len)==0) ) {
821                         *type = ga->avp.type;
822                         *avp_name = ga->avp.name;
823                         return 0;
824                 }
825
826         return -1;
827 }
828
829
830 /* parsing functions */
831 #define ERR_IF_CONTAINS(name,chr) \
832         if (memchr(name->s,chr,name->len)) { \
833                 ERR("Unexpected control character '%c' in AVP name\n", chr); \
834                 goto error; \
835         }
836
837 int parse_avp_name( str *name, int *type, int_str *avp_name, int *index)
838 {
839         int ret;
840         avp_ident_t attr;
841
842         ret=parse_avp_ident(name, &attr);
843         if (!ret) {
844                 if (type) *type = attr.flags;
845                 if (avp_name) *avp_name = attr.name;
846                 if (index) *index = attr.index;
847         }
848         return ret;
849 }
850
851
852 /** parse an avp indentifier.
853  *
854  * Parses the following avp indentifier forms:
855  *       - "i:<number>"  - old form, deprecated  (e.g. i:42)
856  *       - "s:<string>"  - old form, deprecated  (e.g. s:foo)
857  *       - "<track>.<name>"                      (e.g.: f.bar)
858  *       - "<track>.<name>[<index>]"             (e.g.: f.bar[1])
859  *       - "<track><class>.<name>"               (e.g:  tu.bar)
860  *       - "<track><class>.<name>[<index>]"      (e.g:  fd.bar[2])
861  *       - "<string>"                            (e.g.: foo)
862  * Where:
863  *          <string> = ascii string
864  *          <id>   = ascii string w/o '[', ']', '.' and '/'
865  *          <name> = <id> | '/' regex '/'
866  *                   (Note: regex use is deprecated)
867  *          <track> = 'f' | 't'
868  *                   (from or to)
869  *          <class> = 'r' | 'u' | 'd' | 'g'
870  *                    (uri, user, domain or global)
871  *          <index> = <number> | '-' <number> | ''
872  *                    (the avp index, if missing it means AVP_INDEX_ALL, but
873  *                     it's use is deprecated)
874  * More examples:
875  *       "fr.bar[1]"  - from track, uri class, avp "bar", the value 1.
876  *       "tu./^foo/"  - to track,  user class, all avps for which the name
877  *                      starts with foo (note RE in avp names are deprecated).
878  *        "t.did"     - to track, "did" avp
879  *
880  * @param name  - avp identifier
881  * @param *attr - the result will be stored here
882  * @return 0 on success, -1 on error
883  */
884 int parse_avp_ident( str *name, avp_ident_t* attr)
885 {
886         unsigned int id;
887         char c;
888         char *p;
889         str s;
890
891         if (name==0 || name->s==0 || name->len==0) {
892                 ERR("NULL name or name->s or name->len\n");
893                 goto error;
894         }
895
896         attr->index = 0;
897         DBG("Parsing '%.*s'\n", name->len, name->s);
898         if (name->len>=2 && name->s[1]==':') { /* old fashion i: or s: */
899                 /* WARN("i: and s: avp name syntax is deprecated!\n"); */
900                 c = name->s[0];
901                 name->s += 2;
902                 name->len -= 2;
903                 if (name->len==0)
904                         goto error;
905                 switch (c) {
906                         case 's': case 'S':
907                                 attr->flags = AVP_NAME_STR;
908                                 attr->name.s = *name;
909                                 break;
910                         case 'i': case 'I':
911                                 attr->flags = 0;
912                                 if (str2int( name, &id)!=0) {
913                                         ERR("invalid ID "
914                                                 "<%.*s> - not a number\n", name->len, name->s);
915                                         goto error;
916                                 }
917                                 attr->name.n = (int)id;
918                                 break;
919                         default:
920                                 ERR("unsupported type "
921                                         "[%c]\n", c);
922                                 goto error;
923                 }
924         } else if ((p=memchr(name->s, '.', name->len))) {
925                 if (p-name->s==1) {
926                         id=name->s[0];
927                         name->s +=2;
928                         name->len -=2;
929                 } else if (p-name->s==2) {
930                         id=name->s[0]<<8 | name->s[1];
931                         name->s +=3;
932                         name->len -=3;
933                 } else {
934                         ERR("AVP unknown class prefix '%.*s'\n", name->len, name->s);
935                         goto error;
936                 }
937                 if (name->len==0) {
938                         ERR("AVP name not specified after the prefix separator\n");
939                         goto error;
940                 }
941                 switch (id) {
942                         case 'f':
943                                 attr->flags = AVP_TRACK_FROM;
944                                 break;
945                         case 't':
946                                 attr->flags = AVP_TRACK_TO;
947                                 break;
948                         case 0x6672: /* 'fr' */
949                                 attr->flags = AVP_TRACK_FROM | AVP_CLASS_URI;
950                                 break;
951                         case 0x7472: /* 'tr' */
952                                 attr->flags = AVP_TRACK_TO | AVP_CLASS_URI;
953                                 break;                          
954                         case 0x6675: /* 'fu' */
955                                 attr->flags = AVP_TRACK_FROM | AVP_CLASS_USER;
956                                 break;
957                         case 0x7475: /* 'tu' */
958                                 attr->flags = AVP_TRACK_TO | AVP_CLASS_USER;
959                                 break;
960                         case 0x6664: /* 'fd' */
961                                 attr->flags = AVP_TRACK_FROM | AVP_CLASS_DOMAIN;
962                                 break;
963                         case 0x7464: /* 'td' */
964                                 attr->flags = AVP_TRACK_TO | AVP_CLASS_DOMAIN;
965                                 break;
966                         case 'g':
967                                 attr->flags = AVP_TRACK_ALL | AVP_CLASS_GLOBAL;
968                                 break;
969                         default:
970                                 if (id < 1<<8)
971                                         ERR("AVP unknown class prefix '%c'\n", id);
972                                 else
973                                         ERR("AVP unknown class prefix '%c%c'\n", id>>8,id);
974                                 goto error;
975                 }
976                 if (name->s[name->len-1]==']') {
977                         p=memchr(name->s, '[', name->len);
978                         if (!p) {
979                                 ERR("missing '[' for AVP index\n");
980                                 goto error;
981                         }
982                         s.s=p+1;
983                         s.len=name->len-(p-name->s)-2; /* [ and ] */
984                         if (s.len == 0) {
985                                 attr->flags |= AVP_INDEX_ALL;
986                         } else {
987                                 if (s.s[0]=='-') {
988                                         attr->flags |= AVP_INDEX_BACKWARD;
989                                         s.s++;s.len--;
990                                 } else {
991                                         attr->flags |= AVP_INDEX_FORWARD;
992                                 }
993                                 if ((str2int(&s, &id) != 0)||(id==0)) {
994                                         ERR("Invalid AVP index '%.*s'\n", s.len, s.s);
995                                         goto error;
996                                 }
997                                 attr->index = id;
998                         }
999                         name->len=p-name->s;
1000                 }
1001                 ERR_IF_CONTAINS(name,'.');
1002                 ERR_IF_CONTAINS(name,'[');
1003                 ERR_IF_CONTAINS(name,']');
1004                 if ((name->len > 2) && (name->s[0]=='/') && (name->s[name->len-1]=='/')) {
1005                         attr->name.re=pkg_malloc(sizeof(regex_t));
1006                         if (!attr->name.re) {
1007                                 BUG("No free memory to allocate AVP_NAME_RE regex\n");
1008                                 goto error;
1009                         }
1010                         name->s[name->len-1]=0;
1011                         if (regcomp(attr->name.re, name->s+1, REG_EXTENDED|REG_NOSUB|REG_ICASE)) {
1012                                 pkg_free(attr->name.re);
1013                                 attr->name.re=0;
1014                                 name->s[name->len-1] = '/';
1015                                 goto error;
1016                         }
1017                         name->s[name->len-1] = '/';
1018                         attr->flags |= AVP_NAME_RE;
1019                 } else {
1020                         ERR_IF_CONTAINS(name,'/');
1021                         attr->flags |= AVP_NAME_STR;
1022                         attr->name.s = *name;
1023                 }
1024         } else {
1025                 /*default is string name*/
1026                 attr->flags = AVP_NAME_STR;
1027                 attr->name.s = *name;
1028         }
1029
1030         return 0;
1031 error:
1032         return -1;
1033 }
1034
1035 void free_avp_ident(avp_ident_t* attr)
1036 {
1037         if (attr->flags & AVP_NAME_RE) {
1038                 if (! attr->name.re) {
1039                         BUG("attr ident @%p has the regexp flag set, but no regexp.\n",
1040                                         attr);
1041 #ifdef EXTRA_DEBUG
1042                         abort();
1043 #endif
1044                 } else {
1045                         regfree(attr->name.re);
1046                         pkg_free(attr->name.re);
1047                 }
1048         }
1049 }
1050
1051 int km_parse_avp_spec( str *name, int *type, int_str *avp_name)
1052 {
1053         char *p;
1054         int index = 0;
1055
1056         if (name==0 || name->s==0 || name->len==0)
1057                 return -1;
1058
1059         p = (char*)memchr((void*)name->s, ':', name->len);
1060         if (p==NULL) {
1061                 /* might be kamailio avp alias or ser avp name style */
1062                 if(lookup_avp_galias( name, type, avp_name)==0)
1063                         return 0; /* found */
1064         }
1065         return parse_avp_name( name, type, avp_name, &index);
1066 }
1067
1068
1069 int parse_avp_spec( str *name, int *type, int_str *avp_name, int *index)
1070 {
1071         str alias;
1072
1073         if (name==0 || name->s==0 || name->len==0)
1074                 return -1;
1075
1076         if (name->s[0]==GALIAS_CHAR_MARKER) {
1077                 /* it's an avp alias */
1078                 if (name->len==1) {
1079                         LOG(L_ERR,"ERROR:parse_avp_spec: empty alias\n");
1080                         return -1;
1081                 }
1082                 alias.s = name->s+1;
1083                 alias.len = name->len-1;
1084                 return lookup_avp_galias( &alias, type, avp_name);
1085         } else {
1086                 return parse_avp_name( name, type, avp_name, index);
1087         }
1088 }
1089
1090 void free_avp_name(avp_flags_t *type, int_str *avp_name)
1091 {
1092         if ((*type & AVP_NAME_RE) && (avp_name->re)){
1093                 regfree(avp_name->re);
1094                 pkg_free(avp_name->re);
1095                 avp_name->re=0;
1096         }
1097 }
1098
1099 int add_avp_galias_str(char *alias_definition)
1100 {
1101         int_str avp_name;
1102         char *s;
1103         str  name;
1104         str  alias;
1105         int  type;
1106         int  index;
1107
1108         s = alias_definition;
1109         while(*s && isspace((int)*s))
1110                 s++;
1111
1112         while (*s) {
1113                 /* parse alias name */
1114                 alias.s = s;
1115                 while(*s && *s!=';' && !isspace((int)*s) && *s!='=')
1116                         s++;
1117                 if (alias.s==s || *s==0 || *s==';')
1118                         goto parse_error;
1119                 alias.len = s-alias.s;
1120                 while(*s && isspace((int)*s))
1121                         s++;
1122                 /* equal sign */
1123                 if (*s!='=')
1124                         goto parse_error;
1125                 s++;
1126                 while(*s && isspace((int)*s))
1127                         s++;
1128                 /* avp name */
1129                 name.s = s;
1130                 while(*s && *s!=';' && !isspace((int)*s))
1131                         s++;
1132                 if (name.s==s)
1133                         goto parse_error;
1134                 name.len = s-name.s;
1135                 while(*s && isspace((int)*s))
1136                         s++;
1137                 /* check end */
1138                 if (*s!=0 && *s!=';')
1139                         goto parse_error;
1140                 if (*s==';') {
1141                         for( s++ ; *s && isspace((int)*s) ; s++ );
1142                         if (*s==0)
1143                                 goto parse_error;
1144                 }
1145
1146                 if (parse_avp_name( &name, &type, &avp_name, &index)!=0) {
1147                         LOG(L_ERR, "ERROR:add_avp_galias_str: <%.*s> not a valid AVP "
1148                                 "name\n", name.len, name.s);
1149                         goto error;
1150                 }
1151
1152                 if (add_avp_galias( &alias, type, avp_name)!=0) {
1153                         LOG(L_ERR, "ERROR:add_avp_galias_str: add global alias failed\n");
1154                         goto error;
1155                 }
1156         } /*end while*/
1157
1158         return 0;
1159 parse_error:
1160         LOG(L_ERR, "ERROR:add_avp_galias_str: parse error in <%s> around "
1161                 "pos %ld\n", alias_definition, (long)(s-alias_definition));
1162 error:
1163         return -1;
1164 }
1165
1166
1167 int destroy_avps(avp_flags_t flags, avp_name_t name, int all)
1168 {
1169         struct search_state st;
1170         avp_t* avp;
1171         int n;
1172         
1173         n = 0;
1174         avp = search_first_avp(flags, name, 0, &st);
1175         while (avp) {
1176                 destroy_avp(avp);
1177                 n++;
1178                 if (!all) break;
1179                 avp = search_next_avp(&st, 0);
1180         }
1181         return n;
1182 }
1183
1184
1185 void delete_avp(avp_flags_t flags, avp_name_t name)
1186 {
1187         struct search_state st;
1188         avp_t* avp;
1189
1190         avp = search_first_avp(flags, name, 0, &st);
1191         while(avp) {
1192                 destroy_avp(avp);
1193                 avp = search_next_avp(&st, 0);
1194         }
1195 }
1196
1197 /* AVP flags functions */
1198
1199 /* name2id conversion is intended to use during fixup (cfg parsing and modinit) only therefore no hash is used */
1200 avp_flags_t register_avpflag(char* name) {
1201         avp_flags_t ret;
1202         ret = get_avpflag_no(name);
1203         if (ret == 0) {
1204                 if (registered_avpflags_no >= MAX_AVPFLAG) {
1205                         LOG(L_ERR, "register_avpflag: cannot register new avp flag ('%s'), max.number of flags (%d) reached\n", name, MAX_AVPFLAG);
1206                         return -1;
1207                 }
1208                 ret = 1<<(AVP_CUSTOM_FLAGS+registered_avpflags_no);
1209                 registered_avpflags[registered_avpflags_no++] = name;
1210         }
1211         return ret;
1212 }
1213
1214 avp_flags_t get_avpflag_no(char* name) {
1215         int i;
1216         for (i=0; i<registered_avpflags_no; i++) {
1217                 if (strcasecmp(name, registered_avpflags[i])==0)
1218                         return 1<<(AVP_CUSTOM_FLAGS+i);
1219         }
1220         return 0;
1221 }