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