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