Coverage Report

Created: 2025-07-18 06:32

/src/opensips/data_lump.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2010-2014 OpenSIPS Solutions
3
 * Copyright (C) 2001-2003 FhG Fokus
4
 *
5
 * This file is part of opensips, a free SIP server.
6
 *
7
 * opensips is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 2 of the License, or
10
 * (at your option) any later version
11
 *
12
 * opensips is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
20
 *
21
 * History:
22
 * --------
23
 *  2003-01-19  support for duplication lump lists added (jiri)
24
 *  2003-03-31  added subst lumps --they expand in ip addr, port a.s.o (andrei)
25
 *  2003-04-01  added conditional lump support functions (andrei)
26
 *  2003-10-20  anchor_lump & del_lump will automatically choose the lump list
27
 *              based on  msg->eoh comparisons (andrei)
28
 *  2003-10-28  added extra checks (paranoia) for {anchor,del}_lump (andrei)
29
 *  2005-08-22  added init_lump_flags -initial flags- for all built lumps
30
 *              (bogdan)
31
 *  2005-08-23  del_nonshm_lump() -> del_flaged_lumps(LUMPFLAG_SHMEM) (bogdan)
32
 */
33
34
/*!
35
 * \file data_lump.c
36
 * \brief OpenSIPS Lump (internal message manipulation) functions
37
 */
38
39
40
#include "data_lump.h"
41
#include "dprint.h"
42
#include "mem/mem.h"
43
#include "globals.h"
44
#include "error.h"
45
46
#include <stdlib.h>
47
#include <string.h>
48
49
#ifdef DEBUG_DMALLOC
50
#include <dmalloc.h>
51
#endif
52
53
/*! \note WARNING: all lump add/insert operations expect a pkg_malloc'ed char*
54
 * pointer the will be DEALLOCATED when the sip_msg is destroyed! */
55
56
enum lump_dir { LD_NEXT, LD_BEFORE, LD_AFTER };
57
58
int init_lump_flags = 0;
59
60
/*! \brief adds a header to the end
61
 *  \return returns pointer if success, 0 on error
62
 *
63
 * WARNING: currently broken! 
64
 *   - lumps_len() needs to properly handle LUMP_ADD along the main chain of
65
 *     lumps before we can use this
66
 */
67
struct lump* append_new_lump(struct lump** list, char* new_hdr,
68
              unsigned int len, enum _hdr_types_t type)
69
0
{
70
0
  struct lump** t;
71
0
  struct lump* tmp;
72
73
0
  for (t=list;*t;t=&((*t)->next));
74
75
0
  tmp=pkg_malloc(sizeof(struct lump));
76
0
  if (tmp==0){
77
0
    LM_ERR("out of pkg memory\n");
78
0
    return 0;
79
0
  }
80
81
0
  memset(tmp,0,sizeof(struct lump));
82
0
  tmp->type=type;
83
0
  tmp->flags=init_lump_flags;
84
0
  tmp->op=LUMP_ADD;
85
0
  tmp->u.value=new_hdr;
86
0
  tmp->len=len;
87
0
  *t=tmp;
88
0
  return tmp;
89
0
}
90
91
92
93
/*! \brief inserts a header to the beginning
94
 *  \return returns pointer if success, 0 on error
95
 *
96
 * WARNING: currently broken! 
97
 *   - lumps_len() needs to properly handle LUMP_ADD along the main chain of
98
 *     lumps before we can use this
99
 */
100
struct lump* insert_new_lump(struct lump** list, char* new_hdr,
101
                unsigned int len, enum _hdr_types_t type)
102
0
{
103
0
  struct lump* tmp;
104
105
0
  tmp=pkg_malloc(sizeof(struct lump));
106
0
  if (tmp==0){
107
0
    LM_ERR("out of pkg memory\n");
108
0
    return 0;
109
0
  }
110
0
  memset(tmp,0,sizeof(struct lump));
111
0
  tmp->next=*list;
112
0
  tmp->type=type;
113
0
  tmp->flags=init_lump_flags;
114
0
  tmp->op=LUMP_ADD;
115
0
  tmp->u.value=new_hdr;
116
0
  tmp->len=len;
117
0
  *list=tmp;
118
0
  return tmp;
119
0
}
120
121
122
123
/*! \brief inserts a  header/data lump immediately after hdr
124
 * \return returns pointer on success, 0 on error */
125
struct lump* insert_new_lump_after( struct lump* after, char* new_hdr,
126
              unsigned int len, enum _hdr_types_t type)
127
18.5k
{
128
18.5k
  struct lump* tmp;
129
130
18.5k
  tmp=pkg_malloc(sizeof(struct lump));
131
18.5k
  if (tmp==0){
132
0
    ser_error=E_OUT_OF_MEM;
133
0
    LM_ERR("out of pkg memory\n");
134
0
    return 0;
135
0
  }
136
18.5k
  memset(tmp,0,sizeof(struct lump));
137
18.5k
  tmp->after=after->after;
138
18.5k
  tmp->type=type;
139
18.5k
  tmp->flags=init_lump_flags;
140
18.5k
  tmp->op=LUMP_ADD;
141
18.5k
  tmp->u.value=new_hdr;
142
18.5k
  tmp->len=len;
143
18.5k
  after->after=tmp;
144
18.5k
  return tmp;
145
18.5k
}
146
147
148
149
/*! \brief inserts a  header/data lump immediately before "before"
150
 * \return returns pointer on success, 0 on error */
151
struct lump* insert_new_lump_before( struct lump* before, char* new_hdr,
152
              unsigned int len, enum _hdr_types_t type)
153
12.2k
{
154
12.2k
  struct lump* tmp;
155
156
12.2k
  tmp=pkg_malloc(sizeof(struct lump));
157
12.2k
  if (tmp==0){
158
0
    ser_error=E_OUT_OF_MEM;
159
0
    LM_ERR("out of pkg memory\n");
160
0
    return 0;
161
0
  }
162
12.2k
  memset(tmp,0,sizeof(struct lump));
163
12.2k
  tmp->before=before->before;
164
12.2k
  tmp->type=type;
165
12.2k
  tmp->flags=init_lump_flags;
166
12.2k
  tmp->op=LUMP_ADD;
167
12.2k
  tmp->u.value=new_hdr;
168
12.2k
  tmp->len=len;
169
12.2k
  before->before=tmp;
170
12.2k
  return tmp;
171
12.2k
}
172
173
174
175
/*! \brief inserts a  subst lump immediately after hdr
176
 * \return returns pointer on success, 0 on error */
177
struct lump* insert_subst_lump_after( struct lump* after,enum lump_subst subst,
178
                    enum _hdr_types_t type)
179
0
{
180
0
  struct lump* tmp;
181
182
0
  tmp=pkg_malloc(sizeof(struct lump));
183
0
  if (tmp==0){
184
0
    ser_error=E_OUT_OF_MEM;
185
0
    LM_ERR("out of pkg memory\n");
186
0
    return 0;
187
0
  }
188
0
  memset(tmp,0,sizeof(struct lump));
189
0
  tmp->after=after->after;
190
0
  tmp->type=type;
191
0
  tmp->flags=init_lump_flags;
192
0
  tmp->op=LUMP_ADD_SUBST;
193
0
  tmp->u.subst=subst;
194
0
  tmp->len=0;
195
0
  after->after=tmp;
196
0
  return tmp;
197
0
}
198
199
200
201
/*! \brief inserts a  subst lump immediately before "before"
202
 * \return returns pointer on success, 0 on error */
203
struct lump* insert_subst_lump_before(  struct lump* before,
204
                    enum lump_subst subst,
205
                    enum _hdr_types_t type)
206
0
{
207
0
  struct lump* tmp;
208
209
0
  tmp=pkg_malloc(sizeof(struct lump));
210
0
  if (tmp==0){
211
0
    ser_error=E_OUT_OF_MEM;
212
0
    LM_ERR("out of pkg memory\n");
213
0
    return 0;
214
0
  }
215
0
  memset(tmp,0,sizeof(struct lump));
216
0
  tmp->before=before->before;
217
0
  tmp->type=type;
218
0
  tmp->flags=init_lump_flags;
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
228
/*! \brief inserts a  cond lump immediately after hdr
229
 * \return returns pointer on success, 0 on error */
230
struct lump* insert_cond_lump_after( struct lump* after,enum lump_conditions c,
231
                    enum _hdr_types_t type)
232
0
{
233
0
  struct lump* tmp;
234
235
0
  tmp=pkg_malloc(sizeof(struct lump));
236
0
  if (tmp==0){
237
0
    ser_error=E_OUT_OF_MEM;
238
0
    LM_ERR("out of pkg memory\n");
239
0
    return 0;
240
0
  }
241
0
  memset(tmp,0,sizeof(struct lump));
242
0
  tmp->after=after->after;
243
0
  tmp->type=type;
244
0
  tmp->flags=init_lump_flags;
245
0
  tmp->op=LUMP_ADD_OPT;
246
0
  tmp->u.cond=c;
247
0
  tmp->len=0;
248
0
  after->after=tmp;
249
0
  return tmp;
250
0
}
251
252
253
254
/*! \brief inserts a  conditional lump immediately before "before"
255
 * \return returns pointer on success, 0 on error */
256
struct lump* insert_cond_lump_before( struct lump* before,
257
                    enum lump_conditions c,
258
                    enum _hdr_types_t type)
259
0
{
260
0
  struct lump* tmp;
261
262
0
  tmp=pkg_malloc(sizeof(struct lump));
263
0
  if (tmp==0){
264
0
    ser_error=E_OUT_OF_MEM;
265
0
    LM_ERR("out of pkg memory\n");
266
0
    return 0;
267
0
  }
268
0
  memset(tmp,0,sizeof(struct lump));
269
0
  tmp->before=before->before;
270
0
  tmp->type=type;
271
0
  tmp->flags=init_lump_flags;
272
0
  tmp->op=LUMP_ADD_OPT;
273
0
  tmp->u.cond=c;
274
0
  tmp->len=0;
275
0
  before->before=tmp;
276
0
  return tmp;
277
0
}
278
279
280
281
/*! \brief inserts a skip lump immediately after hdr
282
 * \return returns pointer on success, 0 on error */
283
struct lump* insert_skip_lump_after( struct lump* after)
284
0
{
285
0
  struct lump* tmp;
286
287
0
  tmp=pkg_malloc(sizeof(struct lump));
288
0
  if (tmp==0){
289
0
    ser_error=E_OUT_OF_MEM;
290
0
    LM_ERR("out of pkg memory\n");
291
0
    return 0;
292
0
  }
293
0
  memset(tmp,0,sizeof(struct lump));
294
0
  tmp->after=after->after;
295
0
  tmp->flags=init_lump_flags;
296
0
  tmp->op=LUMP_SKIP;
297
0
  after->after=tmp;
298
0
  return tmp;
299
0
}
300
301
302
303
/*! \brief inserts a skip lump immediately before "before"
304
 * \return returns pointer on success, 0 on error */
305
struct lump* insert_skip_lump_before( struct lump* before )
306
0
{
307
0
  struct lump* tmp;
308
309
0
  tmp=pkg_malloc(sizeof(struct lump));
310
0
  if (tmp==0){
311
0
    ser_error=E_OUT_OF_MEM;
312
0
    LM_ERR("out of pkg memory\n");
313
0
    return 0;
314
0
  }
315
0
  memset(tmp,0,sizeof(struct lump));
316
0
  tmp->before=before->before;
317
0
  tmp->flags=init_lump_flags;
318
0
  tmp->op=LUMP_SKIP;
319
0
  before->before=tmp;
320
0
  return tmp;
321
0
}
322
323
324
325
/*! \brief removes an already existing header/data lump */
326
/* WARNING: this function adds the lump either to the msg->add_rm or
327
 * msg->body_lumps list, depending on the offset being greater than msg->eoh,
328
 * so msg->eoh must be parsed (parse with HDR_EOH) if you think your lump
329
 *  might affect the body!! */
330
struct lump* del_lump(struct sip_msg* msg, unsigned int offset,
331
    unsigned int len, enum _hdr_types_t type)
332
105
{
333
105
  struct lump* tmp;
334
105
  struct lump* prev, *t;
335
105
  struct lump** list;
336
337
  /* extra checks */
338
105
  if (offset>msg->len){
339
0
    LM_CRIT("offset exceeds message size (%d > %d)"
340
0
          " aborting...\n", offset, msg->len);
341
0
    abort();
342
0
  }
343
105
  if (offset+len>msg->len){
344
0
    LM_CRIT("offset + len exceeds message"
345
0
        " size (%d + %d > %d)\n", offset, len,  msg->len);
346
0
    abort();
347
0
  }
348
105
  if (len==0){
349
0
    LM_WARN("called with 0 len (offset =%d)\n",  offset);
350
0
  }
351
352
105
  tmp=pkg_malloc(sizeof(struct lump));
353
105
  if (tmp==0){
354
0
    LM_ERR("out of pkg memory\n");
355
0
    return 0;
356
0
  }
357
105
  memset(tmp,0,sizeof(struct lump));
358
105
  tmp->op=LUMP_DEL;
359
105
  tmp->type=type;
360
105
  tmp->flags=init_lump_flags;
361
105
  tmp->u.offset=offset;
362
105
  tmp->len=len;
363
105
  prev=0;
364
  /* check to see whether this might be a body lump */
365
105
  if ((msg->eoh) && (offset>(unsigned long)(msg->eoh-msg->buf)))
366
0
    list=&msg->body_lumps;
367
105
  else
368
105
    list=&msg->add_rm;
369
238
  for (t=*list;t; prev=t, t=t->next){
370
    /* insert it sorted after offset */
371
164
    if (((t->op==LUMP_DEL)||(t->op==LUMP_NOP))&&(t->u.offset>offset))
372
31
      break;
373
164
  }
374
105
  tmp->next=t;
375
105
  if (prev) prev->next=tmp;
376
0
  else *list=tmp;
377
105
  return tmp;
378
105
}
379
380
381
382
/*! \brief add an anchor
383
 * WARNING: this function adds the lump either to the msg->add_rm or
384
 * msg->body_lumps list, depending on the offset being greater than msg->eoh,
385
 * so msg->eoh must be parsed (parse with HDR_EOH) if you think your lump
386
 *  might affect the body!! */
387
struct lump* anchor_lump(struct sip_msg* msg, unsigned int offset,
388
             enum _hdr_types_t type)
389
24.4k
{
390
24.4k
  struct lump* tmp;
391
24.4k
  struct lump* prev, *t;
392
24.4k
  struct lump** list;
393
394
395
  /* extra checks */
396
24.4k
  if (offset>msg->len){
397
0
    LM_CRIT("offset exceeds message size (%d > %d)"
398
0
          " aborting...\n", offset, msg->len);
399
0
    abort();
400
0
  }
401
402
24.4k
  tmp=pkg_malloc(sizeof(struct lump));
403
24.4k
  if (tmp==0){
404
0
    ser_error=E_OUT_OF_MEM;
405
0
    LM_ERR("out of pkg memory\n");
406
0
    return 0;
407
0
  }
408
24.4k
  memset(tmp,0,sizeof(struct lump));
409
24.4k
  tmp->op=LUMP_NOP;
410
24.4k
  tmp->type=type;
411
24.4k
  tmp->flags=init_lump_flags;
412
24.4k
  tmp->u.offset=offset;
413
24.4k
  prev=0;
414
  /* check to see whether this might be a body lump */
415
24.4k
  if ((msg->eoh) && (offset> (unsigned long)(msg->eoh-msg->buf)))
416
0
    list=&msg->body_lumps;
417
24.4k
  else
418
24.4k
    list=&msg->add_rm;
419
420
36.5k
  for (t=*list;t; prev=t, t=t->next){
421
    /* insert it sorted after offset */
422
12.1k
    if (((t->op==LUMP_DEL)||(t->op==LUMP_NOP))&&(t->u.offset>offset))
423
0
      break;
424
12.1k
  }
425
24.4k
  tmp->next=t;
426
427
24.4k
  if (prev) prev->next=tmp;
428
12.2k
  else *list=tmp;
429
24.4k
  return tmp;
430
24.4k
}
431
432
433
434
void free_lump(struct lump* lmp)
435
55.3k
{
436
55.3k
  if (lmp && (lmp->op==LUMP_ADD)){
437
30.8k
    if (lmp->u.value){
438
30.8k
      if (lmp->flags &(LUMPFLAG_SHMEM)){
439
0
        LM_CRIT("called on a not free-able lump:"
440
0
          "%p flags=%x\n", lmp, lmp->flags);
441
0
        abort();
442
30.8k
      }else{
443
30.8k
        pkg_free(lmp->u.value);
444
30.8k
        lmp->u.value=0;
445
30.8k
        lmp->len=0;
446
30.8k
      }
447
30.8k
    }
448
30.8k
  }
449
55.3k
}
450
451
452
453
void free_lump_list(struct lump* l)
454
12.2k
{
455
12.2k
  struct lump* t, *r, *foo,*crt;
456
12.2k
  t=l;
457
36.7k
  while(t){
458
24.5k
    crt=t;
459
24.5k
    t=t->next;
460
461
24.5k
    r=crt->before;
462
36.7k
    while(r){
463
12.2k
      foo=r; r=r->before;
464
12.2k
      free_lump(foo);
465
12.2k
      pkg_free(foo);
466
12.2k
    }
467
24.5k
    r=crt->after;
468
43.1k
    while(r){
469
18.5k
      foo=r; r=r->after;
470
18.5k
      free_lump(foo);
471
18.5k
      pkg_free(foo);
472
18.5k
    }
473
474
    /*clean current elem*/
475
24.5k
    free_lump(crt);
476
24.5k
    pkg_free(crt);
477
24.5k
  }
478
12.2k
}
479
480
481
/*! \brief* duplicate a lump list into pkg memory */
482
static struct lump *dup_lump_list_r( struct lump *l,
483
        enum lump_dir dir, int *error)
484
0
{
485
0
  int deep_error;
486
0
  struct lump *new_lump;
487
488
0
  deep_error=0; /* optimist: assume success in recursion */
489
  /* if at list end, terminate recursion successfully */
490
0
  if (!l) { *error=0; return 0; }
491
  /* otherwise duplicate current element */
492
0
  new_lump=pkg_malloc(sizeof(struct lump));
493
0
  if (!new_lump) { *error=1; return 0; }
494
495
0
  memcpy(new_lump, l, sizeof(struct lump));
496
0
  new_lump->flags=init_lump_flags;
497
0
  new_lump->next=new_lump->before=new_lump->after=0;
498
0
  if (new_lump->op==LUMP_ADD) {
499
0
    new_lump->u.value = pkg_malloc(l->len);
500
0
    if (!new_lump->u.value) { *error=1; return 0; }
501
0
    memcpy(new_lump->u.value,l->u.value,l->len);
502
0
  }
503
504
0
  switch(dir) {
505
0
    case LD_NEXT:
506
0
        new_lump->before=dup_lump_list_r(l->before,
507
0
                LD_BEFORE, &deep_error);
508
0
        if (deep_error) goto deeperror;
509
0
        new_lump->after=dup_lump_list_r(l->after,
510
0
                LD_AFTER, &deep_error);
511
0
        if (deep_error) goto deeperror;
512
0
        new_lump->next=dup_lump_list_r(l->next,
513
0
                LD_NEXT, &deep_error);
514
0
        break;
515
0
    case LD_BEFORE:
516
0
        new_lump->before=dup_lump_list_r(l->before,
517
0
                LD_BEFORE, &deep_error);
518
0
        break;
519
0
    case LD_AFTER:
520
0
        new_lump->after=dup_lump_list_r(l->after,
521
0
                LD_AFTER, &deep_error);
522
0
        break;
523
0
    default:
524
0
        LM_CRIT("unknown dir: %d\n", dir );
525
0
        deep_error=1;
526
0
  }
527
0
  if (deep_error) goto deeperror;
528
529
0
  *error=0;
530
0
  return new_lump;
531
532
0
deeperror:
533
0
  LM_ERR("out of pkg mem\n");
534
0
  free_lump(new_lump);
535
0
  *error=1;
536
0
  return 0;
537
0
}
538
539
540
541
/*! \brief full pkg copy of a lump list
542
 *
543
 * \return if either original list empty or error occur returns, 0
544
 * is returned, pointer to the copy otherwise
545
 */
546
struct lump* dup_lump_list( struct lump *l )
547
0
{
548
0
  int deep_error;
549
550
0
  deep_error=0;
551
0
  return dup_lump_list_r(l, LD_NEXT, &deep_error);
552
0
}
553
554
555
556
/*! \brief Delete flagged lumps
557
 */
558
void del_flaged_lumps( struct lump** lump_list, enum lump_flag flags )
559
0
{
560
0
  struct lump *r, *foo, *crt, **prev, *prev_r;
561
562
0
  prev = lump_list;
563
0
  crt = *lump_list;
564
565
0
  while (crt) {
566
0
    if ( crt->flags&flags ) {
567
      /* unlink it */
568
0
      foo = crt;
569
0
      crt = crt->next;
570
0
      foo->next = 0;
571
      /* update the 'next' link of the previous lump */
572
0
      *prev = crt;
573
      /* entire before/after list must be removed */
574
0
      free_lump_list( foo );
575
0
    } else {
576
      /* check on before and prev list for flaged lumps */
577
0
      r = crt->after;
578
0
      prev_r = crt;
579
0
      while(r){
580
0
        foo=r; r=r->after;
581
0
        if ( foo->flags&flags ) {
582
0
          prev_r->after = r;
583
0
          free_lump(foo);
584
0
          pkg_free(foo);
585
0
        } else {
586
0
          prev_r = foo;
587
0
        }
588
0
      }
589
      /* before */
590
0
      r = crt->before;
591
0
      prev_r = crt;
592
0
      while(r){
593
0
        foo=r; r=r->before;
594
0
        if ( foo->flags&flags ) {
595
0
          prev_r->before = r;
596
0
          free_lump(foo);
597
0
          pkg_free(foo);
598
0
        } else {
599
0
          prev_r = foo;
600
0
        }
601
0
      }
602
      /* go to next lump */
603
0
      prev = &(crt->next);
604
0
      crt = crt->next;
605
0
    }
606
0
  }
607
0
}
608
609
610
/*! \brief Delete not flagged lumps
611
 */
612
void del_notflaged_lumps( struct lump** lump_list, enum lump_flag not_flags )
613
0
{
614
0
  struct lump *r, *foo, *crt, **prev, *prev_r;
615
616
0
  prev = lump_list;
617
0
  crt = *lump_list;
618
619
0
  while (crt) {
620
0
    if ( (~crt->flags)&not_flags ) {
621
      /* unlink it */
622
0
      foo = crt;
623
0
      crt = crt->next;
624
0
      foo->next = 0;
625
      /* update the 'next' link of the previous lump */
626
0
      *prev = crt;
627
      /* entire before/after list must be removed */
628
0
      free_lump_list( foo );
629
0
    } else {
630
      /* check on after and before list for not_flaged lumps */
631
0
      r = crt->after;
632
0
      prev_r = crt;
633
0
      while(r){
634
0
        foo=r; r=r->after;
635
0
        if ( (~foo->flags)&not_flags ) {
636
0
          prev_r->after = r;
637
0
          free_lump(foo);
638
0
          pkg_free(foo);
639
0
        } else {
640
0
          prev_r = foo;
641
0
        }
642
0
      }
643
      /* before */
644
0
      r = crt->before;
645
0
      prev_r = crt;
646
0
      while(r){
647
0
        foo=r; r=r->before;
648
0
        if ( (~foo->flags)&not_flags ) {
649
0
          prev_r->before = r;
650
0
          free_lump(foo);
651
0
          pkg_free(foo);
652
0
        } else {
653
0
          prev_r = foo;
654
0
        }
655
0
      }
656
      /* go to next lump */
657
0
      prev = &(crt->next);
658
0
      crt = crt->next;
659
0
    }
660
0
  }
661
0
}
662