Coverage Report

Created: 2024-02-25 06:34

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