core: pointer aliasing warnings fixed
[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         } else if (flags & AVP_CLASS_GLOBAL) {
132                 return *crt_glist;
133         }
134
135         return NULL;
136 }
137
138 inline static avp_id_t compute_ID( str *name )
139 {
140         char *p;
141         avp_id_t id;
142
143         id=0;
144         for( p=name->s+name->len-1 ; p>=name->s ; p-- )
145                 id ^= *p;
146         return id;
147 }
148
149
150 avp_t *create_avp (avp_flags_t flags, avp_name_t name, avp_value_t val)
151 {
152         avp_t *avp;
153         str *s;
154         struct str_int_data *sid;
155         struct str_str_data *ssd;
156         int len;
157
158         if (name.s.s == 0 && name.s.len == 0) {
159                 LOG(L_ERR,"ERROR:avp:add_avp: 0 ID or NULL NAME AVP!");
160                 goto error;
161         }
162
163         /* compute the required mem size */
164         len = sizeof(struct usr_avp);
165         if (flags&AVP_NAME_STR) {
166                 if ( name.s.s==0 || name.s.len==0) {
167                         LOG(L_ERR,"ERROR:avp:add_avp: EMPTY NAME AVP!");
168                         goto error;
169                 }
170                 if (flags&AVP_VAL_STR) {
171                         len += sizeof(struct str_str_data)-sizeof(union usr_avp_data)
172                                 + name.s.len + 1 /* Terminating zero for regex search */
173                                 + val.s.len + 1; /* Value is zero terminated */
174                 } else {
175                         len += sizeof(struct str_int_data)-sizeof(union usr_avp_data)
176                                 + name.s.len + 1; /* Terminating zero for regex search */
177                 }
178         } else if (flags&AVP_VAL_STR) {
179                 len += sizeof(str)-sizeof(union usr_avp_data) + val.s.len + 1;
180         }
181
182         avp = (struct usr_avp*)shm_malloc( len );
183         if (avp==0) {
184                 LOG(L_ERR,"ERROR:avp:add_avp: no more shm mem\n");
185                 return 0;
186         }
187
188         avp->flags = flags;
189         avp->id = (flags&AVP_NAME_STR)? compute_ID(&name.s) : name.n ;
190         avp->next = NULL;
191
192         switch ( flags&(AVP_NAME_STR|AVP_VAL_STR) )
193         {
194                 case 0:
195                         /* avp type ID, int value */
196                         avp->d.l = val.n;
197                         break;
198                 case AVP_NAME_STR:
199                         /* avp type str, int value */
200                         sid = (struct str_int_data*)&avp->d.data[0];
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*)&avp->d.data[0];
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*)&avp->d.data[0];
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         if (!(list = select_list(flags)))
260                 return -1;
261
262         if (flags & AVP_CLASS_URI) avp_class = AVP_CLASS_URI;
263         else if (flags & AVP_CLASS_USER) avp_class = AVP_CLASS_USER;
264         else if (flags & AVP_CLASS_DOMAIN) avp_class = AVP_CLASS_DOMAIN;
265         else avp_class = AVP_CLASS_GLOBAL;
266
267              /* Make that only the selected class is set
268               * if the caller set more classes in flags
269               */
270         return add_avp_list(list, flags & (~(AVP_CLASS_ALL) | avp_class), name, val);
271 }
272
273 int add_avp_before(avp_t *avp, avp_flags_t flags, avp_name_t name, avp_value_t val)
274 {
275         avp_t *new_avp;
276
277         if (!avp) {
278                 return add_avp(flags, name, val);
279         }
280
281         if ((flags & AVP_CLASS_ALL) == 0) flags |= (avp->flags & AVP_CLASS_ALL);
282         if ((flags & AVP_TRACK_ALL) == 0) flags |= (avp->flags & AVP_TRACK_ALL);
283
284         if ((avp->flags & (AVP_CLASS_ALL|AVP_TRACK_ALL)) != (flags & (AVP_CLASS_ALL|AVP_TRACK_ALL))) {
285                 ERR("add_avp_before:Source and target AVPs have different CLASS/TRACK\n");
286                 return -1;
287         }
288         if ((new_avp=create_avp(flags, name, val))) {
289                 new_avp->next=avp->next;
290                 avp->next=new_avp;
291                 return 0;
292         }
293         return -1;
294 }
295
296 /* get value functions */
297 inline str* get_avp_name(avp_t *avp)
298 {
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                         return &((struct str_int_data*)avp->d.p)->name;
310                 case AVP_NAME_STR|AVP_VAL_STR:
311                         /* avp type str, str value */
312                         return &((struct str_str_data*)avp->d.p)->name;
313         }
314
315         LOG(L_ERR,"BUG:avp:get_avp_name: unknown avp type (name&val) %d\n",
316             avp->flags&(AVP_NAME_STR|AVP_VAL_STR));
317         return 0;
318 }
319
320
321 inline void get_avp_val(avp_t *avp, avp_value_t *val)
322 {
323         
324         if (avp==0 || val==0)
325                 return;
326
327         switch ( avp->flags&(AVP_NAME_STR|AVP_VAL_STR) ) {
328                 case 0:
329                         /* avp type ID, int value */
330                         val->n = avp->d.l;
331                         break;
332                 case AVP_NAME_STR:
333                         /* avp type str, int value */
334                         val->n = ((struct str_int_data*)avp->d.p)->val;
335                         break;
336                 case AVP_VAL_STR:
337                         /* avp type ID, str value */
338                         val->s = *(str*)avp->d.p;
339                         break;
340                 case AVP_NAME_STR|AVP_VAL_STR:
341                         /* avp type str, str value */
342                         val->s = ((struct str_str_data*)avp->d.p)->val;
343                         break;
344         }
345 }
346
347
348 /* Return the current list of user attributes */
349 avp_list_t get_avp_list(avp_flags_t flags)
350 {
351         avp_list_t *list;
352
353         list = select_list(flags);
354         return (list ? *list : NULL);
355 }
356
357
358 /*
359  * Compare given id with id in avp, return true if they match
360  */
361 static inline int match_by_id(avp_t* avp, avp_id_t id)
362 {
363         if (avp->id == id && (avp->flags&AVP_NAME_STR)==0) {
364                 return 1;
365         }
366         return 0;
367 }
368
369
370 /*
371  * Compare given name with name in avp, return true if they are same
372  */
373 static inline int match_by_name(avp_t* avp, avp_id_t id, str* name)
374 {
375         str* avp_name;
376         if (id==avp->id && avp->flags&AVP_NAME_STR &&
377             (avp_name=get_avp_name(avp))!=0 && avp_name->len==name->len
378             && !strncasecmp( avp_name->s, name->s, name->len) ) {
379                 return 1;
380         }
381         return 0;
382 }
383
384
385 /*
386  * Compare name with name in AVP using regular expressions, return
387  * true if they match
388  */
389 static inline int match_by_re(avp_t* avp, regex_t* re)
390 {
391         regmatch_t pmatch;
392         str * avp_name;
393              /* AVP identifiable by name ? */
394         if (!(avp->flags&AVP_NAME_STR)) return 0;
395         if ((avp_name=get_avp_name(avp))==0) /* valid AVP name ? */
396                 return 0;
397         if (!avp_name->s) /* AVP name validation */
398                 return 0;
399         if (regexec(re, avp_name->s, 1, &pmatch,0)==0) { /* re match ? */
400                 return 1;
401         }
402         return 0;
403 }
404
405
406 avp_t *search_first_avp(avp_flags_t flags, avp_name_t name, avp_value_t *val, struct search_state* s)
407 {
408         avp_ident_t id;
409         id.flags = flags;
410         id.name = name;
411         id.index = 0;
412         return search_avp (id, val, s);
413 }
414
415 avp_t *search_avp (avp_ident_t ident, avp_value_t* val, struct search_state* state)
416 {
417         avp_t* ret;
418         static struct search_state st;
419         avp_list_t* list;
420
421         if (ident.name.s.s==0 && ident.name.s.len == 0) {
422                 LOG(L_ERR,"ERROR:avp:search_first_avp: 0 ID or NULL NAME AVP!");
423                 return 0;
424         }
425
426         switch (ident.flags & AVP_INDEX_ALL) {
427                 case AVP_INDEX_BACKWARD:
428                 case AVP_INDEX_FORWARD:
429                         WARN("AVP specified with index, but not used for search\n");
430                         break;
431         }
432
433         if (!state) state = &st;
434
435         if ((ident.flags & AVP_CLASS_ALL) == 0) {
436                      /* The caller did not specify any class to search in, so enable
437                       * all of them by default
438                       */
439                 ident.flags |= AVP_CLASS_ALL;
440
441                 if ((ident.flags & AVP_TRACK_ALL) == 0) {
442                     /* The caller did not specify even the track to search in, so search
443                      * in the track_from
444                      */
445                         ident.flags |= AVP_TRACK_FROM;
446                 }
447         }
448
449         if (!(list = select_list(ident.flags)))
450                 return NULL;
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         avp_list_t *list;
474
475         if (s == 0) {
476                 LOG(L_ERR, "search_next:avp: Invalid parameter value\n");
477                 return 0;
478         }
479
480         switch (s->flags & AVP_INDEX_ALL) {
481                 case AVP_INDEX_BACKWARD:
482                 case AVP_INDEX_FORWARD:
483                         WARN("AVP specified with index, but not used for search\n");
484                         break;
485         }
486
487         while(1) {
488                 for( ; s->avp; s->avp = s->avp->next) {
489                         if (s->flags & AVP_NAME_RE) {
490                                 matched = match_by_re(s->avp, s->name.re);
491                         } else if (s->flags & AVP_NAME_STR) {
492                                 matched = match_by_name(s->avp, s->id, &s->name.s);
493                         } else {
494                                 matched = match_by_id(s->avp, s->name.n);
495                         }
496                         if (matched) {
497                                 avp = s->avp;
498                                 s->avp = s->avp->next;
499                                 if (val) get_avp_val(avp, val);
500                                 return avp;
501                         }
502                 }
503
504                 if (s->flags & AVP_CLASS_URI) {
505                         s->flags &= ~AVP_CLASS_URI;
506                         list = select_list(s->flags);
507                 } else if (s->flags & AVP_CLASS_USER) {
508                         s->flags &= ~AVP_CLASS_USER;
509                         list = select_list(s->flags);
510                 } else if (s->flags & AVP_CLASS_DOMAIN) {
511                         s->flags &= ~AVP_CLASS_DOMAIN;
512                         list = select_list(s->flags);
513                 } else {
514                         s->flags &= ~AVP_CLASS_GLOBAL;
515                         return 0;
516                 }
517                 if (!list) return 0;
518                 s->avp = *list;
519         }
520
521         return 0;
522 }
523
524 int search_reverse( avp_t *cur, struct search_state* st,
525                      avp_index_t index, avp_list_t *ret)
526 {
527         avp_index_t lvl;
528
529         if (!cur)
530                 return 0;
531         lvl = search_reverse(search_next_avp(st, NULL), st, index, ret)+1;
532         if (index==lvl)
533                 *ret=cur;
534         return lvl;
535 }
536
537 avp_t *search_avp_by_index( avp_flags_t flags, avp_name_t name,
538                             avp_value_t *val, avp_index_t index)
539 {
540         avp_t *ret, *cur;
541         struct search_state st;
542
543         if (flags & AVP_NAME_RE) {
544                 BUG("search_by_index not supported for AVP_NAME_RE\n");
545                 return 0;
546         }
547         switch (flags & AVP_INDEX_ALL) {
548                 case 0:
549                         ret = search_first_avp(flags, name, val, &st);
550                         if (!ret || search_next_avp(&st, NULL))
551                                 return 0;
552                         else
553                                 return ret;
554                 case AVP_INDEX_ALL:
555                         BUG("search_by_index not supported for anonymous index []\n");
556                         return 0;
557                 case AVP_INDEX_FORWARD:
558                         ret = NULL;
559                         cur = search_first_avp(flags & ~AVP_INDEX_ALL, name, NULL, &st);
560                         search_reverse(cur, &st, index, &ret);
561                         if (ret && val)
562                                 get_avp_val(ret, val);
563                         return ret;
564                 case AVP_INDEX_BACKWARD:
565                         ret = search_first_avp(flags & ~AVP_INDEX_ALL, name, val, &st);
566                         for (index--; (ret && index); ret=search_next_avp(&st, val), index--);
567                         return ret;
568         }
569
570         return 0;
571 }
572
573 /* FIXME */
574 /********* free functions ********/
575
576 void destroy_avp(avp_t *avp_del)
577 {
578         int i;
579         avp_t *avp, *avp_prev;
580
581         for (i = 0; i < IDX_MAX; i++) {
582                 for( avp_prev=0,avp=*crt_list[i] ; avp ;
583                      avp_prev=avp,avp=avp->next ) {
584                         if (avp==avp_del) {
585                                 if (avp_prev) {
586                                         avp_prev->next=avp->next;
587                                 } else {
588                                         *crt_list[i] = avp->next;
589                                 }
590                                 shm_free(avp);
591                                 return;
592                         }
593                 }
594         }
595
596         for( avp_prev=0,avp=**crt_glist ; avp ;
597              avp_prev=avp,avp=avp->next ) {
598                 if (avp==avp_del) {
599                         if (avp_prev) {
600                                 avp_prev->next=avp->next;
601                         } else {
602                                 **crt_glist = avp->next;
603                         }
604                         shm_free(avp);
605                         return;
606                 }
607         }
608 }
609
610
611 void destroy_avp_list_unsafe(avp_list_t* list)
612 {
613         avp_t *avp, *foo;
614
615         avp = *list;
616         while( avp ) {
617                 foo = avp;
618                 avp = avp->next;
619                 shm_free_unsafe( foo );
620         }
621         *list = 0;
622 }
623
624
625 inline void destroy_avp_list(avp_list_t* list)
626 {
627         avp_t *avp, *foo;
628
629         DBG("DEBUG:destroy_avp_list: destroying list %p\n", *list);
630         avp = *list;
631         while( avp ) {
632                 foo = avp;
633                 avp = avp->next;
634                 shm_free( foo );
635         }
636         *list = 0;
637 }
638
639 int reset_avp_list(int flags)
640 {
641     int i;
642     if (flags & AVP_CLASS_URI) {
643         if (flags & AVP_TRACK_FROM) i = IDX_FROM_URI;
644         else i = IDX_TO_URI;
645     } else if (flags & AVP_CLASS_USER) {
646         if (flags & AVP_TRACK_FROM) i = IDX_FROM_USER;
647         else i = IDX_TO_USER;
648     } else if (flags & AVP_CLASS_DOMAIN) {
649         if (flags & AVP_TRACK_FROM) i = IDX_FROM_DOMAIN;
650         else i = IDX_TO_DOMAIN;
651     } else return -1;
652
653     crt_list[i] = &def_list[i];
654     destroy_avp_list(crt_list[i]);
655     return 0;
656 }
657
658 void reset_avps(void)
659 {
660         int i;
661         for(i = 0; i < IDX_MAX; i++) {
662                 crt_list[i] = &def_list[i];
663                 destroy_avp_list(crt_list[i]);
664         }
665 }
666
667
668 avp_list_t* set_avp_list( avp_flags_t flags, avp_list_t* list )
669 {
670         avp_list_t* prev;
671
672         if (flags & AVP_CLASS_URI) {
673                 if (flags & AVP_TRACK_FROM) {
674                         prev = crt_list[IDX_FROM_URI];
675                         crt_list[IDX_FROM_URI] = list;
676                 } else {
677                         prev = crt_list[IDX_TO_URI];
678                         crt_list[IDX_TO_URI] = list;
679                 }
680         } else if (flags & AVP_CLASS_USER) {
681                 if (flags & AVP_TRACK_FROM) {
682                         prev = crt_list[IDX_FROM_USER];
683                         crt_list[IDX_FROM_USER] = list;
684                 } else {
685                         prev = crt_list[IDX_TO_USER];
686                         crt_list[IDX_TO_USER] = list;
687                 }
688         } else if (flags & AVP_CLASS_DOMAIN) {
689                 if (flags & AVP_TRACK_FROM) {
690                         prev = crt_list[IDX_FROM_DOMAIN];
691                         crt_list[IDX_FROM_DOMAIN] = list;
692                 } else {
693                         prev = crt_list[IDX_TO_DOMAIN];
694                         crt_list[IDX_TO_DOMAIN] = list;
695                 }
696         } else {
697                 prev = *crt_glist;
698                 *crt_glist = list;
699         }
700
701         return prev;
702 }
703
704
705 /********* global aliases functions ********/
706
707 static inline int check_avp_galias(str *alias, int type, int_str avp_name)
708 {
709         struct avp_galias *ga;
710
711         type &= AVP_NAME_STR;
712
713         for( ga=galiases ; ga ; ga=ga->next ) {
714                 /* check for duplicated alias names */
715                 if ( alias->len==ga->alias.len &&
716                 (strncasecmp( alias->s, ga->alias.s, alias->len)==0) )
717                         return -1;
718                 /*check for duplicated avp names */
719                 if (type==ga->avp.type) {
720                         if (type&AVP_NAME_STR){
721                                 if (avp_name.s.len==ga->avp.name.s.len &&
722                                     (strncasecmp(avp_name.s.s, ga->avp.name.s.s,
723                                                  avp_name.s.len)==0) )
724                                         return -1;
725                         } else {
726                                 if (avp_name.n==ga->avp.name.n)
727                                         return -1;
728                         }
729                 }
730         }
731         return 0;
732 }
733
734
735 int add_avp_galias(str *alias, int type, int_str avp_name)
736 {
737         struct avp_galias *ga;
738
739         if ((type&AVP_NAME_STR && (!avp_name.s.s ||
740                                    !avp_name.s.len)) ||!alias || !alias->s ||
741                 !alias->len ){
742                 LOG(L_ERR, "ERROR:add_avp_galias: null params received\n");
743                 goto error;
744         }
745
746         if (check_avp_galias(alias,type,avp_name)!=0) {
747                 LOG(L_ERR, "ERROR:add_avp_galias: duplicate alias/avp entry\n");
748                 goto error;
749         }
750
751         ga = (struct avp_galias*)pkg_malloc( sizeof(struct avp_galias) );
752         if (ga==0) {
753                 LOG(L_ERR, "ERROR:add_avp_galias: no more pkg memory\n");
754                 goto error;
755         }
756
757         ga->alias.s = (char*)pkg_malloc( alias->len+1 );
758         if (ga->alias.s==0) {
759                 LOG(L_ERR, "ERROR:add_avp_galias: no more pkg memory\n");
760                 goto error1;
761         }
762         memcpy( ga->alias.s, alias->s, alias->len);
763         ga->alias.len = alias->len;
764
765         ga->avp.type = type&AVP_NAME_STR;
766
767         if (type&AVP_NAME_STR) {
768                 ga->avp.name.s.s = (char*)pkg_malloc( avp_name.s.len+1 );
769                 if (ga->avp.name.s.s==0) {
770                         LOG(L_ERR, "ERROR:add_avp_galias: no more pkg memory\n");
771                         goto error2;
772                 }
773                 ga->avp.name.s.len = avp_name.s.len;
774                 memcpy( ga->avp.name.s.s, avp_name.s.s, avp_name.s.len);
775                 ga->avp.name.s.s[avp_name.s.len] = 0;
776                 DBG("DEBUG:add_avp_galias: registering <%s> for avp name <%s>\n",
777                         ga->alias.s, ga->avp.name.s.s);
778         } else {
779                 ga->avp.name.n = avp_name.n;
780                 DBG("DEBUG:add_avp_galias: registering <%s> for avp id <%d>\n",
781                         ga->alias.s, ga->avp.name.n);
782         }
783
784         ga->next = galiases;
785         galiases = ga;
786
787         return 0;
788 error2:
789         pkg_free(ga->alias.s);
790 error1:
791         pkg_free(ga);
792 error:
793         return -1;
794 }
795
796
797 int lookup_avp_galias(str *alias, int *type, int_str *avp_name)
798 {
799         struct avp_galias *ga;
800
801         for( ga=galiases ; ga ; ga=ga->next )
802                 if (alias->len==ga->alias.len &&
803                 (strncasecmp( alias->s, ga->alias.s, alias->len)==0) ) {
804                         *type = ga->avp.type;
805                         *avp_name = ga->avp.name;
806                         return 0;
807                 }
808
809         return -1;
810 }
811
812
813 /* parsing functions */
814 #define ERR_IF_CONTAINS(name,chr) \
815         if (memchr(name->s,chr,name->len)) { \
816                 ERR("Unexpected control character '%c' in AVP name\n", chr); \
817                 goto error; \
818         }
819
820 int parse_avp_name( str *name, int *type, int_str *avp_name, int *index)
821 {
822         int ret;
823         avp_ident_t attr;
824
825         ret=parse_avp_ident(name, &attr);
826         if (!ret) {
827                 if (type) *type = attr.flags;
828                 if (avp_name) *avp_name = attr.name;
829                 if (index) *index = attr.index;
830         }
831         return ret;
832 }
833
834
835 /** parse an avp indentifier.
836  *
837  * Parses the following avp indentifier forms:
838  *       - "i:<number>"  - old form, deprecated  (e.g. i:42)
839  *       - "s:<string>"  - old form, deprecated  (e.g. s:foo)
840  *       - "<track>.<name>"                      (e.g.: f.bar)
841  *       - "<track>.<name>[<index>]"             (e.g.: f.bar[1])
842  *       - "<track><class>.<name>"               (e.g:  tu.bar)
843  *       - "<track><class>.<name>[<index>]"      (e.g:  fd.bar[2])
844  *       - "<string>"                            (e.g.: foo)
845  * Where:
846  *          <string> = ascii string
847  *          <id>   = ascii string w/o '[', ']', '.' and '/'
848  *          <name> = <id> | '/' regex '/'
849  *                   (Note: regex use is deprecated)
850  *          <track> = 'f' | 't'
851  *                   (from or to)
852  *          <class> = 'r' | 'u' | 'd' | 'g'
853  *                    (uri, user, domain or global)
854  *          <index> = <number> | '-' <number> | ''
855  *                    (the avp index, if missing it means AVP_INDEX_ALL, but
856  *                     it's use is deprecated)
857  * More examples:
858  *       "fr.bar[1]"  - from track, uri class, avp "bar", the value 1.
859  *       "tu./^foo/"  - to track,  user class, all avps for which the name
860  *                      starts with foo (note RE in avp names are deprecated).
861  *        "t.did"     - to track, "did" avp
862  *
863  * @param name  - avp identifier
864  * @param *attr - the result will be stored here
865  * @return 0 on success, -1 on error
866  */
867 int parse_avp_ident( str *name, avp_ident_t* attr)
868 {
869         unsigned int id;
870         char c;
871         char *p;
872         str s;
873
874         if (name==0 || name->s==0 || name->len==0) {
875                 ERR("NULL name or name->s or name->len\n");
876                 goto error;
877         }
878
879         attr->index = 0;
880         DBG("Parsing '%.*s'\n", name->len, name->s);
881         if (name->len>=2 && name->s[1]==':') { /* old fashion i: or s: */
882                 /* WARN("i: and s: avp name syntax is deprecated!\n"); */
883                 c = name->s[0];
884                 name->s += 2;
885                 name->len -= 2;
886                 if (name->len==0)
887                         goto error;
888                 switch (c) {
889                         case 's': case 'S':
890                                 attr->flags = AVP_NAME_STR;
891                                 attr->name.s = *name;
892                                 break;
893                         case 'i': case 'I':
894                                 attr->flags = 0;
895                                 if (str2int( name, &id)!=0) {
896                                         ERR("invalid ID "
897                                                 "<%.*s> - not a number\n", name->len, name->s);
898                                         goto error;
899                                 }
900                                 attr->name.n = (int)id;
901                                 break;
902                         default:
903                                 ERR("unsupported type "
904                                         "[%c]\n", c);
905                                 goto error;
906                 }
907         } else if ((p=memchr(name->s, '.', name->len))) {
908                 if (p-name->s==1) {
909                         id=name->s[0];
910                         name->s +=2;
911                         name->len -=2;
912                 } else if (p-name->s==2) {
913                         id=name->s[0]<<8 | name->s[1];
914                         name->s +=3;
915                         name->len -=3;
916                 } else {
917                         ERR("AVP unknown class prefix '%.*s'\n", name->len, name->s);
918                         goto error;
919                 }
920                 if (name->len==0) {
921                         ERR("AVP name not specified after the prefix separator\n");
922                         goto error;
923                 }
924                 switch (id) {
925                         case 'f':
926                                 attr->flags = AVP_TRACK_FROM;
927                                 break;
928                         case 't':
929                                 attr->flags = AVP_TRACK_TO;
930                                 break;
931                         case 0x6672: /* 'fr' */
932                                 attr->flags = AVP_TRACK_FROM | AVP_CLASS_URI;
933                                 break;
934                         case 0x7472: /* 'tr' */
935                                 attr->flags = AVP_TRACK_TO | AVP_CLASS_URI;
936                                 break;                          
937                         case 0x6675: /* 'fu' */
938                                 attr->flags = AVP_TRACK_FROM | AVP_CLASS_USER;
939                                 break;
940                         case 0x7475: /* 'tu' */
941                                 attr->flags = AVP_TRACK_TO | AVP_CLASS_USER;
942                                 break;
943                         case 0x6664: /* 'fd' */
944                                 attr->flags = AVP_TRACK_FROM | AVP_CLASS_DOMAIN;
945                                 break;
946                         case 0x7464: /* 'td' */
947                                 attr->flags = AVP_TRACK_TO | AVP_CLASS_DOMAIN;
948                                 break;
949                         case 'g':
950                                 attr->flags = AVP_TRACK_ALL | AVP_CLASS_GLOBAL;
951                                 break;
952                         default:
953                                 if (id < 1<<8)
954                                         ERR("AVP unknown class prefix '%c'\n", id);
955                                 else
956                                         ERR("AVP unknown class prefix '%c%c'\n", id>>8,id);
957                                 goto error;
958                 }
959                 if (name->s[name->len-1]==']') {
960                         p=memchr(name->s, '[', name->len);
961                         if (!p) {
962                                 ERR("missing '[' for AVP index\n");
963                                 goto error;
964                         }
965                         s.s=p+1;
966                         s.len=name->len-(p-name->s)-2; /* [ and ] */
967                         if (s.len == 0) {
968                                 attr->flags |= AVP_INDEX_ALL;
969                         } else {
970                                 if (s.s[0]=='-') {
971                                         attr->flags |= AVP_INDEX_BACKWARD;
972                                         s.s++;s.len--;
973                                 } else {
974                                         attr->flags |= AVP_INDEX_FORWARD;
975                                 }
976                                 if ((str2int(&s, &id) != 0)||(id==0)) {
977                                         ERR("Invalid AVP index '%.*s'\n", s.len, s.s);
978                                         goto error;
979                                 }
980                                 attr->index = id;
981                         }
982                         name->len=p-name->s;
983                 }
984                 ERR_IF_CONTAINS(name,'.');
985                 ERR_IF_CONTAINS(name,'[');
986                 ERR_IF_CONTAINS(name,']');
987                 if ((name->len > 2) && (name->s[0]=='/') && (name->s[name->len-1]=='/')) {
988                         attr->name.re=pkg_malloc(sizeof(regex_t));
989                         if (!attr->name.re) {
990                                 BUG("No free memory to allocate AVP_NAME_RE regex\n");
991                                 goto error;
992                         }
993                         name->s[name->len-1]=0;
994                         if (regcomp(attr->name.re, name->s+1, REG_EXTENDED|REG_NOSUB|REG_ICASE)) {
995                                 pkg_free(attr->name.re);
996                                 attr->name.re=0;
997                                 name->s[name->len-1] = '/';
998                                 goto error;
999                         }
1000                         name->s[name->len-1] = '/';
1001                         attr->flags |= AVP_NAME_RE;
1002                 } else {
1003                         ERR_IF_CONTAINS(name,'/');
1004                         attr->flags |= AVP_NAME_STR;
1005                         attr->name.s = *name;
1006                 }
1007         } else {
1008                 /*default is string name*/
1009                 attr->flags = AVP_NAME_STR;
1010                 attr->name.s = *name;
1011         }
1012
1013         return 0;
1014 error:
1015         return -1;
1016 }
1017
1018 void free_avp_ident(avp_ident_t* attr)
1019 {
1020         if (attr->flags & AVP_NAME_RE) {
1021                 if (! attr->name.re) {
1022                         BUG("attr ident @%p has the regexp flag set, but no regexp.\n",
1023                                         attr);
1024 #ifdef EXTRA_DEBUG
1025                         abort();
1026 #endif
1027                 } else {
1028                         regfree(attr->name.re);
1029                         pkg_free(attr->name.re);
1030                 }
1031         }
1032 }
1033
1034 int km_parse_avp_spec( str *name, int *type, int_str *avp_name)
1035 {
1036         char *p;
1037         int index = 0;
1038
1039         if (name==0 || name->s==0 || name->len==0)
1040                 return -1;
1041
1042         p = (char*)memchr((void*)name->s, ':', name->len);
1043         if (p==NULL) {
1044                 /* might be kamailio avp alias or ser avp name style */
1045                 if(lookup_avp_galias( name, type, avp_name)==0)
1046                         return 0; /* found */
1047         }
1048         return parse_avp_name( name, type, avp_name, &index);
1049 }
1050
1051
1052 int parse_avp_spec( str *name, int *type, int_str *avp_name, int *index)
1053 {
1054         str alias;
1055
1056         if (name==0 || name->s==0 || name->len==0)
1057                 return -1;
1058
1059         if (name->s[0]==GALIAS_CHAR_MARKER) {
1060                 /* it's an avp alias */
1061                 if (name->len==1) {
1062                         LOG(L_ERR,"ERROR:parse_avp_spec: empty alias\n");
1063                         return -1;
1064                 }
1065                 alias.s = name->s+1;
1066                 alias.len = name->len-1;
1067                 return lookup_avp_galias( &alias, type, avp_name);
1068         } else {
1069                 return parse_avp_name( name, type, avp_name, index);
1070         }
1071 }
1072
1073 void free_avp_name(avp_flags_t *type, int_str *avp_name)
1074 {
1075         if ((*type & AVP_NAME_RE) && (avp_name->re)){
1076                 regfree(avp_name->re);
1077                 pkg_free(avp_name->re);
1078                 avp_name->re=0;
1079         }
1080 }
1081
1082 int add_avp_galias_str(char *alias_definition)
1083 {
1084         int_str avp_name;
1085         char *s;
1086         str  name;
1087         str  alias;
1088         int  type;
1089         int  index;
1090
1091         s = alias_definition;
1092         while(*s && isspace((int)*s))
1093                 s++;
1094
1095         while (*s) {
1096                 /* parse alias name */
1097                 alias.s = s;
1098                 while(*s && *s!=';' && !isspace((int)*s) && *s!='=')
1099                         s++;
1100                 if (alias.s==s || *s==0 || *s==';')
1101                         goto parse_error;
1102                 alias.len = s-alias.s;
1103                 while(*s && isspace((int)*s))
1104                         s++;
1105                 /* equal sign */
1106                 if (*s!='=')
1107                         goto parse_error;
1108                 s++;
1109                 while(*s && isspace((int)*s))
1110                         s++;
1111                 /* avp name */
1112                 name.s = s;
1113                 while(*s && *s!=';' && !isspace((int)*s))
1114                         s++;
1115                 if (name.s==s)
1116                         goto parse_error;
1117                 name.len = s-name.s;
1118                 while(*s && isspace((int)*s))
1119                         s++;
1120                 /* check end */
1121                 if (*s!=0 && *s!=';')
1122                         goto parse_error;
1123                 if (*s==';') {
1124                         for( s++ ; *s && isspace((int)*s) ; s++ );
1125                         if (*s==0)
1126                                 goto parse_error;
1127                 }
1128
1129                 if (parse_avp_name( &name, &type, &avp_name, &index)!=0) {
1130                         LOG(L_ERR, "ERROR:add_avp_galias_str: <%.*s> not a valid AVP "
1131                                 "name\n", name.len, name.s);
1132                         goto error;
1133                 }
1134
1135                 if (add_avp_galias( &alias, type, avp_name)!=0) {
1136                         LOG(L_ERR, "ERROR:add_avp_galias_str: add global alias failed\n");
1137                         goto error;
1138                 }
1139         } /*end while*/
1140
1141         return 0;
1142 parse_error:
1143         LOG(L_ERR, "ERROR:add_avp_galias_str: parse error in <%s> around "
1144                 "pos %ld\n", alias_definition, (long)(s-alias_definition));
1145 error:
1146         return -1;
1147 }
1148
1149
1150 int destroy_avps(avp_flags_t flags, avp_name_t name, int all)
1151 {
1152         struct search_state st;
1153         avp_t* avp;
1154         int n;
1155         
1156         n = 0;
1157         avp = search_first_avp(flags, name, 0, &st);
1158         while (avp) {
1159                 destroy_avp(avp);
1160                 n++;
1161                 if (!all) break;
1162                 avp = search_next_avp(&st, 0);
1163         }
1164         return n;
1165 }
1166
1167
1168 void delete_avp(avp_flags_t flags, avp_name_t name)
1169 {
1170         struct search_state st;
1171         avp_t* avp;
1172
1173         avp = search_first_avp(flags, name, 0, &st);
1174         while(avp) {
1175                 destroy_avp(avp);
1176                 avp = search_next_avp(&st, 0);
1177         }
1178 }
1179
1180 /* AVP flags functions */
1181
1182 /* name2id conversion is intended to use during fixup (cfg parsing and modinit) only therefore no hash is used */
1183 avp_flags_t register_avpflag(char* name) {
1184         avp_flags_t ret;
1185         ret = get_avpflag_no(name);
1186         if (ret == 0) {
1187                 if (registered_avpflags_no >= MAX_AVPFLAG) {
1188                         LOG(L_ERR, "register_avpflag: cannot register new avp flag ('%s'), max.number of flags (%d) reached\n", name, MAX_AVPFLAG);
1189                         return -1;
1190                 }
1191                 ret = 1<<(AVP_CUSTOM_FLAGS+registered_avpflags_no);
1192                 registered_avpflags[registered_avpflags_no++] = name;
1193         }
1194         return ret;
1195 }
1196
1197 avp_flags_t get_avpflag_no(char* name) {
1198         int i;
1199         for (i=0; i<registered_avpflags_no; i++) {
1200                 if (strcasecmp(name, registered_avpflags[i])==0)
1201                         return 1<<(AVP_CUSTOM_FLAGS+i);
1202         }
1203         return 0;
1204 }