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