Coverage Report

Created: 2024-02-25 06:34

/src/kamailio/src/core/data_lump.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
 * \file
23
 * \brief Kamailio core :: Data lumps
24
 * \ingroup core
25
 * Module: \ref core
26
 */
27
28
29
#include "data_lump.h"
30
#include "dprint.h"
31
#include "mem/mem.h"
32
#include "globals.h"
33
#include "error.h"
34
35
#include <stdlib.h>
36
#include <string.h>
37
38
#ifdef DEBUG_DMALLOC
39
#include <dmalloc.h>
40
#endif
41
42
/* WARNING: all lump add/insert operations expect a pkg_malloc'ed char*
43
 * pointer the will be DEALLOCATED when the sip_msg is destroyed! */
44
45
enum lump_dir
46
{
47
  LD_NEXT,
48
  LD_BEFORE,
49
  LD_AFTER
50
};
51
52
/* adds text content to the end of lump list
53
 * returns  pointer on success, 0 on error */
54
struct lump *append_new_lump(
55
    struct lump **list, char *txt, int len, enum _hdr_types_t type)
56
0
{
57
0
  struct lump **t;
58
0
  struct lump *tmp;
59
60
0
  for(t = list; *t; t = &((*t)->next))
61
0
    ;
62
63
0
  tmp = pkg_malloc(sizeof(struct lump));
64
0
  if(tmp == 0) {
65
0
    ser_error = E_OUT_OF_MEM;
66
0
    PKG_MEM_ERROR;
67
0
    return 0;
68
0
  }
69
70
0
  memset(tmp, 0, sizeof(struct lump));
71
0
  tmp->type = type;
72
0
  tmp->op = LUMP_ADD;
73
0
  tmp->u.value = txt;
74
0
  tmp->len = len;
75
0
  *t = tmp;
76
0
  return tmp;
77
0
}
78
79
/* adds text content right after an anchor (list) point if exists
80
 * returns  pointer on success, 0 on error */
81
struct lump *add_new_lump(
82
    struct lump **list, char *txt, int len, enum _hdr_types_t type)
83
0
{
84
0
  struct lump **t;
85
0
  struct lump *tmp;
86
87
0
  t = (*list) ? &((*list)->next) : list;
88
89
0
  tmp = pkg_malloc(sizeof(struct lump));
90
0
  if(tmp == 0) {
91
0
    ser_error = E_OUT_OF_MEM;
92
0
    PKG_MEM_ERROR;
93
0
    return 0;
94
0
  }
95
96
0
  memset(tmp, 0, sizeof(struct lump));
97
0
  tmp->type = type;
98
0
  tmp->op = LUMP_ADD;
99
0
  tmp->u.value = txt;
100
0
  tmp->len = len;
101
0
  tmp->next = *t;
102
0
  *t = tmp;
103
0
  return tmp;
104
0
}
105
106
107
/* inserts text content to the beginning of lump list
108
 * returns pointer if success, 0 on error */
109
struct lump *insert_new_lump(
110
    struct lump **list, char *txt, int len, enum _hdr_types_t type)
111
0
{
112
0
  struct lump *tmp;
113
114
0
  tmp = pkg_malloc(sizeof(struct lump));
115
0
  if(tmp == 0) {
116
0
    ser_error = E_OUT_OF_MEM;
117
0
    PKG_MEM_ERROR;
118
0
    return 0;
119
0
  }
120
0
  memset(tmp, 0, sizeof(struct lump));
121
0
  tmp->next = *list;
122
0
  tmp->type = type;
123
0
  tmp->op = LUMP_ADD;
124
0
  tmp->u.value = txt;
125
0
  tmp->len = len;
126
0
  *list = tmp;
127
0
  return tmp;
128
0
}
129
130
131
/* inserts text content (data lump) immediately after lump pointer
132
 * returns pointer on success, 0 on error */
133
struct lump *insert_new_lump_after(
134
    struct lump *after, char *txt, int len, enum _hdr_types_t type)
135
0
{
136
0
  struct lump *tmp;
137
138
0
  tmp = pkg_malloc(sizeof(struct lump));
139
0
  if(tmp == 0) {
140
0
    ser_error = E_OUT_OF_MEM;
141
0
    PKG_MEM_ERROR;
142
0
    return 0;
143
0
  }
144
0
  memset(tmp, 0, sizeof(struct lump));
145
0
  tmp->after = after->after;
146
0
  tmp->type = type;
147
0
  tmp->op = LUMP_ADD;
148
0
  tmp->u.value = txt;
149
0
  tmp->len = len;
150
0
  after->after = tmp;
151
0
  return tmp;
152
0
}
153
154
155
/* inserts a  header/data lump immediately before the lump "before"
156
 * returns pointer on success, 0 on error */
157
struct lump *insert_new_lump_before(
158
    struct lump *before, char *txt, int len, enum _hdr_types_t type)
159
0
{
160
0
  struct lump *tmp;
161
162
0
  tmp = pkg_malloc(sizeof(struct lump));
163
0
  if(tmp == 0) {
164
0
    ser_error = E_OUT_OF_MEM;
165
0
    PKG_MEM_ERROR;
166
0
    return 0;
167
0
  }
168
0
  memset(tmp, 0, sizeof(struct lump));
169
0
  tmp->before = before->before;
170
0
  tmp->type = type;
171
0
  tmp->op = LUMP_ADD;
172
0
  tmp->u.value = txt;
173
0
  tmp->len = len;
174
0
  before->before = tmp;
175
0
  return tmp;
176
0
}
177
178
179
/* inserts a subst lump immediately after the lump "after"
180
 * returns pointer on success, 0 on error */
181
struct lump *insert_subst_lump_after(
182
    struct lump *after, enum lump_subst subst, enum _hdr_types_t type)
183
0
{
184
0
  struct lump *tmp;
185
186
0
  tmp = pkg_malloc(sizeof(struct lump));
187
0
  if(tmp == 0) {
188
0
    ser_error = E_OUT_OF_MEM;
189
0
    PKG_MEM_ERROR;
190
0
    return 0;
191
0
  }
192
0
  memset(tmp, 0, sizeof(struct lump));
193
0
  tmp->after = after->after;
194
0
  tmp->type = type;
195
0
  tmp->op = LUMP_ADD_SUBST;
196
0
  tmp->u.subst = subst;
197
0
  tmp->len = 0;
198
0
  after->after = tmp;
199
0
  return tmp;
200
0
}
201
202
203
/* inserts a subst lump immediately before the lump "before"
204
 * returns pointer on success, 0 on error */
205
struct lump *insert_subst_lump_before(
206
    struct lump *before, enum lump_subst subst, enum _hdr_types_t type)
207
0
{
208
0
  struct lump *tmp;
209
210
0
  tmp = pkg_malloc(sizeof(struct lump));
211
0
  if(tmp == 0) {
212
0
    ser_error = E_OUT_OF_MEM;
213
0
    PKG_MEM_ERROR;
214
0
    return 0;
215
0
  }
216
0
  memset(tmp, 0, sizeof(struct lump));
217
0
  tmp->before = before->before;
218
0
  tmp->type = type;
219
0
  tmp->op = LUMP_ADD_SUBST;
220
0
  tmp->u.subst = subst;
221
0
  tmp->len = 0;
222
0
  before->before = tmp;
223
0
  return tmp;
224
0
}
225
226
227
/* inserts a  cond lump immediately after the lump "after"
228
 * returns pointer on success, 0 on error */
229
struct lump *insert_cond_lump_after(
230
    struct lump *after, enum lump_conditions c, enum _hdr_types_t type)
231
0
{
232
0
  struct lump *tmp;
233
234
0
  tmp = pkg_malloc(sizeof(struct lump));
235
0
  if(tmp == 0) {
236
0
    ser_error = E_OUT_OF_MEM;
237
0
    PKG_MEM_ERROR;
238
0
    return 0;
239
0
  }
240
0
  memset(tmp, 0, sizeof(struct lump));
241
0
  tmp->after = after->after;
242
0
  tmp->type = type;
243
0
  tmp->op = LUMP_ADD_OPT;
244
0
  tmp->u.cond = c;
245
0
  tmp->len = 0;
246
0
  after->after = tmp;
247
0
  return tmp;
248
0
}
249
250
251
/* inserts a  conditional lump immediately before the lump "before"
252
 * returns pointer on success, 0 on error */
253
struct lump *insert_cond_lump_before(
254
    struct lump *before, enum lump_conditions c, enum _hdr_types_t type)
255
0
{
256
0
  struct lump *tmp;
257
258
0
  tmp = pkg_malloc(sizeof(struct lump));
259
0
  if(tmp == 0) {
260
0
    ser_error = E_OUT_OF_MEM;
261
0
    PKG_MEM_ERROR;
262
0
    return 0;
263
0
  }
264
0
  memset(tmp, 0, sizeof(struct lump));
265
0
  tmp->before = before->before;
266
0
  tmp->type = type;
267
0
  tmp->op = LUMP_ADD_OPT;
268
0
  tmp->u.cond = c;
269
0
  tmp->len = 0;
270
0
  before->before = tmp;
271
0
  return tmp;
272
0
}
273
274
275
/* removes an already existing content with a data lump */
276
/* WARNING: this function adds the lump either to the msg->add_rm or
277
 * msg->body_lumps list, depending on the offset being greater than msg->eoh,
278
 * so msg->eoh must be parsed (parse with HDR_EOH) if you think your lump
279
 *  might affect the body!! */
280
struct lump *del_lump(
281
    struct sip_msg *msg, int offset, int len, enum _hdr_types_t type)
282
0
{
283
0
  struct lump *tmp;
284
0
  struct lump *prev, *t;
285
0
  struct lump **list;
286
287
  /* extra checks */
288
0
  if(offset > msg->len) {
289
0
    LM_CRIT("offset exceeds message size (%d > %d)\n", offset, msg->len);
290
0
    return 0;
291
0
  }
292
0
  if(offset + len > msg->len) {
293
0
    LM_CRIT("offset + len exceeds message size (%d + %d > %d)\n", offset,
294
0
        len, msg->len);
295
0
    return 0;
296
0
  }
297
0
  if(len == 0) {
298
0
    LM_WARN("0 len (offset=%d)\n", offset);
299
0
  }
300
301
0
  tmp = pkg_malloc(sizeof(struct lump));
302
0
  if(tmp == 0) {
303
0
    ser_error = E_OUT_OF_MEM;
304
0
    PKG_MEM_ERROR;
305
0
    return 0;
306
0
  }
307
0
  memset(tmp, 0, sizeof(struct lump));
308
0
  tmp->op = LUMP_DEL;
309
0
  tmp->type = type;
310
0
  tmp->u.offset = offset;
311
0
  tmp->len = len;
312
0
  prev = 0;
313
  /* check to see whether this might be a body lump */
314
0
  if((msg->eoh) && (offset > (int)(msg->eoh - msg->buf)))
315
0
    list = &msg->body_lumps;
316
0
  else
317
0
    list = &msg->add_rm;
318
0
  for(t = *list; t; prev = t, t = t->next) {
319
    /* insert it sorted after offset */
320
0
    if(((t->op == LUMP_DEL) || (t->op == LUMP_NOP))
321
0
        && (t->u.offset > offset))
322
0
      break;
323
0
  }
324
0
  tmp->next = t;
325
0
  if(prev)
326
0
    prev->next = tmp;
327
0
  else
328
0
    *list = tmp;
329
0
  return tmp;
330
0
}
331
332
333
/* add an anchor
334
 * WARNING: this function adds the lump either to the msg->add_rm or
335
 * msg->body_lumps list, depending on the offset being greater than msg->eoh,
336
 * so msg->eoh must be parsed (parse with HDR_EOH) if you think your lump
337
 *  might affect the body!! */
338
struct lump *anchor_lump(
339
    struct sip_msg *msg, int offset, int len, enum _hdr_types_t type)
340
0
{
341
0
  struct lump *tmp;
342
0
  struct lump *prev, *t;
343
0
  struct lump **list;
344
345
  /* extra checks */
346
0
  if(offset > msg->len) {
347
0
    LM_CRIT("offset exceeds message size (%d > %d)\n", offset, msg->len);
348
0
    return 0;
349
0
  }
350
0
  if(len) {
351
0
    LM_WARN("len !=0 (%d)\n", len);
352
0
    if(offset + len > msg->len)
353
0
      LM_WARN("offset + len exceeds message size (%d + %d > %d)\n",
354
0
          offset, len, msg->len);
355
0
  }
356
357
0
  tmp = pkg_malloc(sizeof(struct lump));
358
0
  if(tmp == 0) {
359
0
    ser_error = E_OUT_OF_MEM;
360
0
    PKG_MEM_ERROR;
361
0
    return 0;
362
0
  }
363
0
  memset(tmp, 0, sizeof(struct lump));
364
0
  tmp->op = LUMP_NOP;
365
0
  tmp->type = type;
366
0
  tmp->u.offset = offset;
367
0
  tmp->len = len;
368
0
  prev = 0;
369
  /* check to see whether this might be a body lump */
370
0
  if((msg->eoh) && (offset > (int)(msg->eoh - msg->buf)))
371
0
    list = &msg->body_lumps;
372
0
  else
373
0
    list = &msg->add_rm;
374
375
0
  for(t = *list; t; prev = t, t = t->next) {
376
    /* insert it sorted after offset */
377
0
    if(((t->op == LUMP_DEL) || (t->op == LUMP_NOP))
378
0
        && (t->u.offset > offset))
379
0
      break;
380
0
  }
381
0
  tmp->next = t;
382
383
0
  if(prev)
384
0
    prev->next = tmp;
385
0
  else
386
0
    *list = tmp;
387
0
  return tmp;
388
0
}
389
390
/* add an anchor
391
 * Similar to anchor_lump() but this function checks whether or not a lump
392
 * has already been added to the same position. If an existing lump is found
393
 * then it is returned without adding a new one and is_ref is set to 1.
394
 *
395
 * WARNING: this function adds the lump either to the msg->add_rm or
396
 * msg->body_lumps list, depending on the offset being greater than msg->eoh,
397
 * so msg->eoh must be parsed (parse with HDR_EOH) if you think your lump
398
 *  might affect the body!! */
399
struct lump *anchor_lump2(struct sip_msg *msg, int offset, int len,
400
    enum _hdr_types_t type, int *is_ref)
401
0
{
402
0
  struct lump *tmp;
403
0
  struct lump *prev, *t;
404
0
  struct lump **list;
405
406
  /* extra checks */
407
0
  if(offset > msg->len) {
408
0
    LM_CRIT("offset exceeds message size (%d > %d)\n", offset, msg->len);
409
0
    return 0;
410
0
  }
411
0
  if(len) {
412
0
    LM_WARN("len !=0 (%d)\n", len);
413
0
    if(offset + len > msg->len)
414
0
      LM_WARN("offset + len exceeds message size (%d + %d > %d)\n",
415
0
          offset, len, msg->len);
416
0
  }
417
418
0
  prev = 0;
419
  /* check to see whether this might be a body lump */
420
0
  if((msg->eoh) && (offset > (int)(msg->eoh - msg->buf)))
421
0
    list = &msg->body_lumps;
422
0
  else
423
0
    list = &msg->add_rm;
424
425
0
  for(t = *list; t; prev = t, t = t->next) {
426
    /* insert it sorted after offset */
427
0
    if(((t->op == LUMP_DEL) || (t->op == LUMP_NOP))
428
0
        && (t->u.offset >= offset))
429
0
      break;
430
0
  }
431
0
  if(t && (t->u.offset == offset)) {
432
    /* A lump with the same offset is found */
433
0
    *is_ref = 1;
434
0
    return t;
435
0
  }
436
437
0
  tmp = pkg_malloc(sizeof(struct lump));
438
0
  if(tmp == 0) {
439
0
    ser_error = E_OUT_OF_MEM;
440
0
    PKG_MEM_ERROR;
441
0
    return 0;
442
0
  }
443
0
  memset(tmp, 0, sizeof(struct lump));
444
0
  tmp->op = LUMP_NOP;
445
0
  tmp->type = type;
446
0
  tmp->u.offset = offset;
447
0
  tmp->len = len;
448
449
0
  tmp->next = t;
450
451
0
  if(prev)
452
0
    prev->next = tmp;
453
0
  else
454
0
    *list = tmp;
455
456
0
  *is_ref = 0;
457
0
  return tmp;
458
0
}
459
460
461
/**
462
 * free lump content
463
 */
464
void free_lump(struct lump *lmp)
465
0
{
466
0
  if(lmp && (lmp->op == LUMP_ADD)) {
467
0
    if(lmp->u.value) {
468
0
      if(lmp->flags & LUMPFLAG_SHMEM) {
469
0
        LM_CRIT("non free-able lump: %p flags=%x\n", lmp, lmp->flags);
470
0
        abort();
471
0
      } else if(!(lmp->flags & LUMPFLAG_DUPED)) {
472
0
        pkg_free(lmp->u.value);
473
0
        lmp->u.value = 0;
474
0
        lmp->len = 0;
475
0
      }
476
0
    }
477
0
  }
478
0
}
479
480
481
void free_lump_list(struct lump *l)
482
0
{
483
0
  struct lump *t, *r, *foo, *crt;
484
0
  t = l;
485
0
  while(t) {
486
0
    crt = t;
487
0
    t = t->next;
488
    /*
489
    dangerous recursive clean
490
    if (crt->before) free_lump_list(crt->before);
491
    if (crt->after)  free_lump_list(crt->after);
492
  */
493
    /* no more recursion, clean after and before and that's it */
494
0
    r = crt->before;
495
0
    while(r) {
496
0
      foo = r;
497
0
      r = r->before;
498
0
      free_lump(foo);
499
0
      pkg_free(foo);
500
0
    }
501
0
    r = crt->after;
502
0
    while(r) {
503
0
      foo = r;
504
0
      r = r->after;
505
0
      free_lump(foo);
506
0
      pkg_free(foo);
507
0
    }
508
509
    /*clean current elem*/
510
0
    free_lump(crt);
511
0
    pkg_free(crt);
512
0
  }
513
0
}
514
515
/* free (shallow-ly) a lump and its after/before lists */
516
static void free_shallow_lump(struct lump *l)
517
0
{
518
0
  struct lump *r, *foo;
519
520
0
  r = l->before;
521
0
  while(r) {
522
0
    foo = r;
523
0
    r = r->before;
524
0
    pkg_free(foo);
525
0
  }
526
0
  r = l->after;
527
0
  while(r) {
528
0
    foo = r;
529
0
    r = r->after;
530
0
    pkg_free(foo);
531
0
  }
532
0
  pkg_free(l);
533
0
}
534
535
/* duplicate (shallow-ly) a lump list into pkg memory */
536
static struct lump *dup_lump_list_r(
537
    struct lump *l, enum lump_dir dir, int *error)
538
0
{
539
0
  int deep_error;
540
0
  struct lump *new_lump;
541
542
0
  deep_error = 0; /* optimist: assume success in recursion */
543
  /* if at list end, terminate recursion successfully */
544
0
  if(!l) {
545
0
    *error = 0;
546
0
    return 0;
547
0
  }
548
  /* otherwise duplicate current element */
549
0
  new_lump = pkg_malloc(sizeof(struct lump));
550
0
  if(!new_lump) {
551
0
    ser_error = E_OUT_OF_MEM;
552
0
    PKG_MEM_ERROR;
553
0
    *error = 1;
554
0
    return 0;
555
0
  }
556
557
0
  memcpy(new_lump, l, sizeof(struct lump));
558
0
  new_lump->flags = LUMPFLAG_DUPED;
559
0
  new_lump->next = new_lump->before = new_lump->after = 0;
560
561
0
  switch(dir) {
562
0
    case LD_NEXT:
563
0
      new_lump->before =
564
0
          dup_lump_list_r(l->before, LD_BEFORE, &deep_error);
565
0
      if(deep_error)
566
0
        goto deeperror;
567
0
      new_lump->after = dup_lump_list_r(l->after, LD_AFTER, &deep_error);
568
0
      if(deep_error)
569
0
        goto deeperror;
570
0
      new_lump->next = dup_lump_list_r(l->next, LD_NEXT, &deep_error);
571
0
      break;
572
0
    case LD_BEFORE:
573
0
      new_lump->before =
574
0
          dup_lump_list_r(l->before, LD_BEFORE, &deep_error);
575
0
      break;
576
0
    case LD_AFTER:
577
0
      new_lump->after = dup_lump_list_r(l->after, LD_AFTER, &deep_error);
578
0
      break;
579
0
    default:
580
0
      LM_CRIT("unknown dir: %d\n", dir);
581
0
      deep_error = 1;
582
0
  }
583
0
  if(deep_error)
584
0
    goto deeperror;
585
586
0
  *error = 0;
587
0
  return new_lump;
588
589
0
deeperror:
590
0
  LM_ERR("out of mem\n");
591
0
  free_shallow_lump(new_lump);
592
0
  *error = 1;
593
0
  return 0;
594
0
}
595
596
597
/* shallow pkg copy of a lump list
598
 *
599
 * if either original list empty or error occur returns, 0
600
 * is returned, pointer to the copy otherwise
601
 */
602
struct lump *dup_lump_list(struct lump *l)
603
0
{
604
0
  int deep_error;
605
606
0
  deep_error = 0;
607
0
  return dup_lump_list_r(l, LD_NEXT, &deep_error);
608
0
}
609
610
611
void free_duped_lump_list(struct lump *l)
612
0
{
613
0
  struct lump *r, *foo, *crt;
614
0
  while(l) {
615
0
    crt = l;
616
0
    l = l->next;
617
618
0
    r = crt->before;
619
0
    while(r) {
620
0
      foo = r;
621
0
      r = r->before;
622
      /* (+): if a new item was introduced to the shallow-ly
623
       * duped list, remove it completely, preserve it
624
       * otherwise (it is still referred by original list)
625
       */
626
0
      if(foo->flags != LUMPFLAG_DUPED)
627
0
        free_lump(foo);
628
0
      pkg_free(foo);
629
0
    }
630
0
    r = crt->after;
631
0
    while(r) {
632
0
      foo = r;
633
0
      r = r->after;
634
0
      if(foo->flags != LUMPFLAG_DUPED) /* (+) ... see above */
635
0
        free_lump(foo);
636
0
      pkg_free(foo);
637
0
    }
638
639
    /*clean current elem*/
640
0
    if(crt->flags != LUMPFLAG_DUPED) /* (+) ... see above */
641
0
      free_lump(crt);
642
0
    pkg_free(crt);
643
0
  }
644
0
}
645
646
647
void del_nonshm_lump(struct lump **lump_list)
648
0
{
649
0
  struct lump *r, *foo, *crt, **prev, *prev_r;
650
651
0
  prev = lump_list;
652
0
  crt = *lump_list;
653
654
0
  while(crt) {
655
0
    if(!(crt->flags & LUMPFLAG_SHMEM)) {
656
      /* unlink it */
657
0
      foo = crt;
658
0
      crt = crt->next;
659
0
      foo->next = 0;
660
      /* update the 'next' link of the previous lump */
661
0
      *prev = crt;
662
      /* entire before/after list must be removed */
663
0
      free_lump_list(foo);
664
0
    } else {
665
      /* check on before and prev list for non-shmem lumps */
666
0
      r = crt->after;
667
0
      prev_r = crt;
668
0
      while(r) {
669
0
        foo = r;
670
0
        r = r->after;
671
0
        if(!(foo->flags & LUMPFLAG_SHMEM)) {
672
0
          prev_r->after = r;
673
0
          free_lump(foo);
674
0
          pkg_free(foo);
675
0
        } else {
676
0
          prev_r = foo;
677
0
        }
678
0
      }
679
      /* before */
680
0
      r = crt->before;
681
0
      prev_r = crt;
682
0
      while(r) {
683
0
        foo = r;
684
0
        r = r->before;
685
0
        if(!(foo->flags & LUMPFLAG_SHMEM)) {
686
0
          prev_r->before = r;
687
0
          free_lump(foo);
688
0
          pkg_free(foo);
689
0
        } else {
690
0
          prev_r = foo;
691
0
        }
692
0
      }
693
      /* go to next lump */
694
0
      prev = &(crt->next);
695
0
      crt = crt->next;
696
0
    }
697
0
  }
698
0
}
699
700
unsigned int count_applied_lumps(struct lump *ll, int type)
701
0
{
702
0
  unsigned int n = 0;
703
0
  struct lump *l = 0;
704
705
0
  for(l = ll; l; l = l->next) {
706
0
    if(l->op == LUMP_NOP && l->type == type) {
707
0
      if(l->after && l->after->op == LUMP_ADD_OPT) {
708
0
        if(LUMP_IS_COND_TRUE(l->after)) {
709
0
          n++;
710
0
        }
711
0
      } else {
712
0
        n++;
713
0
      }
714
0
    }
715
0
  }
716
0
  return n;
717
0
}
718
719
/**
720
 * remove a lump in a root list
721
 * - it doesn't look for lumps added as before/after rule
722
 * - destroys the entire lump, with associated before/after rules
723
 */
724
int remove_lump(sip_msg_t *msg, struct lump *l)
725
0
{
726
0
  struct lump *t = NULL;
727
0
  struct lump *prev = NULL;
728
0
  struct lump **list = NULL;
729
730
0
  list = &msg->add_rm;
731
0
  for(t = *list; t; prev = t, t = t->next) {
732
0
    if(t == l)
733
0
      break;
734
0
  }
735
0
  if(t == NULL) {
736
0
    list = &msg->body_lumps;
737
0
    for(t = *list; t; prev = t, t = t->next) {
738
0
      if(t == l)
739
0
        break;
740
0
    }
741
0
  }
742
0
  if(t != NULL) {
743
0
    if(prev == NULL) {
744
0
      *list = t->next;
745
0
    } else {
746
0
      prev->next = t->next;
747
0
    }
748
    /* detach and free all its content */
749
0
    t->next = NULL;
750
0
    free_lump_list(t);
751
0
    return 1;
752
0
  }
753
0
  return 0;
754
0
}
755
756
/**
757
 *
758
 */
759
int sr_hdr_add(sip_msg_t *msg, str *sname, str *sbody)
760
0
{
761
0
  struct lump *anchor;
762
0
  str h;
763
764
0
  if(parse_headers(msg, HDR_EOH_F, 0) < 0 || msg->last_header == 0) {
765
0
    LM_ERR("failed to parse headers\n");
766
0
    return -1;
767
0
  }
768
0
  h.len = sname->len + 2 + sbody->len + CRLF_LEN;
769
0
  h.s = (char *)pkg_malloc(h.len + 1);
770
0
  if(h.s == 0) {
771
0
    ser_error = E_OUT_OF_MEM;
772
0
    PKG_MEM_ERROR;
773
0
    return -1;
774
0
  }
775
0
  anchor = anchor_lump(msg,
776
0
      msg->last_header->name.s + msg->last_header->len - msg->buf, 0, 0);
777
0
  if(anchor == 0) {
778
0
    LM_ERR("cannot get the anchor\n");
779
0
    pkg_free(h.s);
780
0
    return -1;
781
0
  }
782
0
  memcpy(h.s, sname->s, sname->len);
783
0
  memcpy(h.s + sname->len, ": ", 2);
784
0
  memcpy(h.s + sname->len + 2, sbody->s, sbody->len);
785
0
  memcpy(h.s + sname->len + 2 + sbody->len, CRLF, CRLF_LEN);
786
0
  h.s[h.len] = '\0';
787
0
  if(insert_new_lump_after(anchor, h.s, h.len, 0) == 0) {
788
0
    LM_ERR("cannot insert lump\n");
789
0
    pkg_free(h.s);
790
0
    return -1;
791
0
  }
792
0
  LM_DBG("added new header (%d) [%s]\n", h.len, h.s);
793
0
  return 0;
794
0
}
795
796
/**
797
 *
798
 */
799
int sr_hdr_add_zz(sip_msg_t *msg, char *hname, char *hbody)
800
0
{
801
0
  str sname;
802
0
  str sbody;
803
804
0
  sname.s = hname;
805
0
  sname.len = strlen(sname.s);
806
0
  sbody.s = hbody;
807
0
  sbody.len = strlen(sbody.s);
808
809
0
  return sr_hdr_add(msg, &sname, &sbody);
810
0
}
811
812
/**
813
 *
814
 */
815
int sr_hdr_add_zs(sip_msg_t *msg, char *hname, str *sbody)
816
0
{
817
0
  str sname;
818
819
0
  sname.s = hname;
820
0
  sname.len = strlen(sname.s);
821
822
0
  return sr_hdr_add(msg, &sname, sbody);
823
0
}
824
825
/**
826
 *
827
 */
828
hdr_field_t *sr_hdr_get_z(sip_msg_t *msg, char *hname)
829
0
{
830
0
  hdr_field_t *hf;
831
0
  str sname;
832
833
0
  sname.s = hname;
834
0
  sname.len = strlen(sname.s);
835
836
0
  for(hf = msg->headers; hf; hf = hf->next) {
837
0
    if(hf->name.len == sname.len
838
0
        && strncasecmp(hf->name.s, sname.s, sname.len) == 0) {
839
0
      return hf;
840
0
    }
841
0
  }
842
0
  return NULL;
843
0
}
844
845
/**
846
 *
847
 */
848
int sr_hdr_del_z(sip_msg_t *msg, char *hname)
849
0
{
850
0
  hdr_field_t *hf;
851
0
  struct lump *l;
852
0
  str sname;
853
854
0
  sname.s = hname;
855
0
  sname.len = strlen(sname.s);
856
857
0
  for(hf = msg->headers; hf; hf = hf->next) {
858
0
    if(hf->name.len == sname.len
859
0
        && strncasecmp(hf->name.s, sname.s, sname.len) == 0) {
860
0
      l = del_lump(msg, hf->name.s - msg->buf, hf->len, 0);
861
0
      if(l == 0) {
862
0
        LM_ERR("unable to delete cookie header\n");
863
0
        return -1;
864
0
      }
865
0
      return 0;
866
0
    }
867
0
  }
868
0
  return 0;
869
0
}