GPLization banner introduced to *.[hc] files
[sip-router] / modules / tm / sip_msg.c
1 /*
2  * $Id$
3  * 
4  * cloning a message into shared memory (TM keeps a snapshot
5  * of messages in memory); note that many operations, which
6  * allocate pkg memory (such as parsing) cannot be used with
7  * a cloned message -- it would result in linking pkg structures
8  * to shmem msg and eventually in a memory error 
9  *
10  * the cloned message is stored in a single memory fragment to
11  * save too many shm_mallocs -- these are expensive as they
12  * not only take lookup in fragment table but also a shmem lock
13  * operation (the same for shm_free)
14  *
15  * Copyright (C) 2001-2003 Fhg Fokus
16  *
17  * This file is part of ser, a free SIP server.
18  *
19  * ser is free software; you can redistribute it and/or modify
20  * it under the terms of the GNU General Public License as published by
21  * the Free Software Foundation; either version 2 of the License, or
22  * (at your option) any later version
23  *
24  * For a license to use the ser software under conditions
25  * other than those described here, or to purchase support for this
26  * software, please contact iptel.org by e-mail at the following addresses:
27  *    info@iptel.org
28  *
29  * ser is distributed in the hope that it will be useful,
30  * but WITHOUT ANY WARRANTY; without even the implied warranty of
31  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
32  * GNU General Public License for more details.
33  *
34  * You should have received a copy of the GNU General Public License 
35  * along with this program; if not, write to the Free Software 
36  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
37  */
38
39
40 #include <stdio.h>
41 #include "sip_msg.h"
42 #include "../../dprint.h"
43 #include "../../mem/mem.h"
44 #include "../../data_lump.h"
45 #include "../../data_lump_rpl.h"
46 #include "../../ut.h"
47
48
49
50 #define ROUND4(s) \
51         (((s)+3)&(~(3UL)))
52 #define lump_len( _lump) \
53         (ROUND4(sizeof(struct lump)) +\
54         ROUND4(((_lump)->op==LUMP_ADD)?(_lump)->len:0))
55 #define lump_clone( _new,_old,_ptr) \
56         {\
57                 (_new) = (struct lump*)(_ptr);\
58                 memcpy( (_new), (_old), sizeof(struct lump) );\
59                 (_ptr)+=ROUND4(sizeof(struct lump));\
60                 if ( (_old)->op==LUMP_ADD) {\
61                         (_new)->u.value = (char*)(_ptr);\
62                         memcpy( (_new)->u.value , (_old)->u.value , (_old)->len);\
63                         (_ptr)+=ROUND4((_old)->len);}\
64         }
65
66
67
68
69 inline struct via_body* via_body_cloner( char* new_buf,
70                                         char *org_buf, struct via_body *param_org_via, char **p)
71 {
72         struct via_body *new_via;
73         struct via_body *first_via, *last_via;
74         struct via_body *org_via;
75
76         first_via = last_via = 0;
77         org_via = param_org_via;
78
79         do
80         {
81                 /* clones the via_body structure */
82                 new_via = (struct via_body*)(*p);
83                 memcpy( new_via , org_via , sizeof( struct via_body) );
84                 (*p) += ROUND4(sizeof( struct via_body ));
85
86                 /* hdr (str type) */
87                 new_via->hdr.s=translate_pointer(new_buf,org_buf,org_via->hdr.s);
88                 /* name (str type) */
89                 new_via->name.s=translate_pointer(new_buf,org_buf,org_via->name.s);
90                 /* version (str type) */
91                 new_via->version.s=
92                         translate_pointer(new_buf,org_buf,org_via->version.s);
93                 /* transport (str type) */
94                 new_via->transport.s=
95                         translate_pointer(new_buf,org_buf,org_via->transport.s);
96                 /* host (str type) */
97                 new_via->host.s=translate_pointer(new_buf,org_buf,org_via->host.s);
98                 /* port_str (str type) */
99                 new_via->port_str.s=
100                         translate_pointer(new_buf,org_buf,org_via->port_str.s);
101                 /* params (str type) */
102                 new_via->params.s=translate_pointer(new_buf,org_buf,org_via->params.s);
103                 /* comment (str type) */
104                 new_via->comment.s=
105                         translate_pointer(new_buf,org_buf,org_via->comment.s);
106
107                 if ( org_via->param_lst )
108                 {
109                         struct via_param *vp, *new_vp, *last_new_vp;
110                         for( vp=org_via->param_lst, last_new_vp=0 ; vp ; vp=vp->next )
111                         {
112                                 new_vp = (struct via_param*)(*p);
113                                 memcpy( new_vp , vp , sizeof(struct via_param));
114                                 (*p) += ROUND4(sizeof(struct via_param));
115                                 new_vp->name.s=translate_pointer(new_buf,org_buf,vp->name.s);
116                                 new_vp->value.s=translate_pointer(new_buf,org_buf,vp->value.s);
117
118                                 if (new_vp->type==PARAM_BRANCH)
119                                         new_via->branch = new_vp;
120
121                                 if (last_new_vp)
122                                         last_new_vp->next = new_vp;
123                                 else
124                                         new_via->param_lst = new_vp;
125
126                                 last_new_vp = new_vp;
127                                 last_new_vp->next = NULL;
128                         }
129                         new_via->last_param = new_vp;
130                 }/*end if via has params */
131
132                 if (last_via)
133                         last_via->next = new_via;
134                 else
135                         first_via = new_via;
136                 last_via = new_via;
137                 org_via = org_via->next;
138         }while(org_via);
139
140         return first_via;
141 }
142
143
144
145
146 struct sip_msg*  sip_msg_cloner( struct sip_msg *org_msg )
147 {
148         unsigned int      len;
149         struct hdr_field  *hdr,*new_hdr,*last_hdr;
150         struct via_body   *via;
151         struct via_param  *prm;
152         struct to_param   *to_prm,*new_to_prm;
153         struct sip_msg    *new_msg;
154         struct lump       *lump_chain, *lump_tmp, **lump_anchor, **lump_anchor2;
155         struct lump_rpl   *rpl_lump, **rpl_lump_anchor;
156         char              *p,*foo;
157
158
159         /*computing the length of entire sip_msg structure*/
160         len = ROUND4(sizeof( struct sip_msg ));
161         /*we will keep only the original msg +ZT */
162         len += ROUND4(org_msg->len + 1);
163         /*the new uri (if any)*/
164         if (org_msg->new_uri.s && org_msg->new_uri.len)
165                 len+= ROUND4(org_msg->new_uri.len);
166         /*all the headers*/
167         for( hdr=org_msg->headers ; hdr ; hdr=hdr->next )
168         {
169                 /*size of header struct*/
170                 len += ROUND4(sizeof( struct hdr_field));
171                 switch (hdr->type)
172                 {
173                         case HDR_CSEQ:
174                                 len+=ROUND4(sizeof(struct cseq_body));
175                                 break;
176                         case HDR_TO:
177                                 len+=ROUND4(sizeof(struct to_body));
178                                 /*to param*/
179                                 to_prm = ((struct to_body*)(hdr->parsed))->param_lst;
180                                 for(;to_prm;to_prm=to_prm->next)
181                                         len+=ROUND4(sizeof(struct to_param ));
182                                 break;
183                         case HDR_VIA:
184                                 for (via=(struct via_body*)hdr->parsed;via;via=via->next)
185                                 {
186                                         len+=ROUND4(sizeof(struct via_body));
187                                         /*via param*/
188                                         for(prm=via->param_lst;prm;prm=prm->next)
189                                                 len+=ROUND4(sizeof(struct via_param ));
190                                 }
191                                 break;
192                         case HDR_PROXYAUTH:
193                                 /* we frequently parse this HF but don't use it in TM --
194                                    just keep silent about it
195                                 */
196                                 break;
197                         default:
198                                 if (hdr->parsed) {
199                                         LOG(L_WARN, "WARNING: sip_msg_cloner: "
200                                                 "header body ignored: %d\n", hdr->type );
201                                 }
202                                 break;
203                 }/*switch*/
204         }/*for all headers*/
205
206         /* length of the data lump structures */
207         if (org_msg->first_line.type==SIP_REQUEST)
208                 lump_chain = org_msg->add_rm;
209         else
210                 lump_chain = org_msg->repl_add_rm;
211         while (lump_chain)
212         {
213                 len += lump_len( lump_chain );
214                 lump_tmp = lump_chain->before;
215                 while ( lump_tmp )
216                 {
217                         len += lump_len( lump_tmp );
218                         lump_tmp = lump_tmp->before;
219                 }
220                 lump_tmp = lump_chain->after;
221                 while ( lump_tmp )
222                 {
223                         len += lump_len( lump_tmp );
224                         lump_tmp = lump_tmp->after;
225                 }
226                 lump_chain = lump_chain->next;
227         }
228
229         /*length of reply lump structures*/
230         for(rpl_lump=org_msg->reply_lump;rpl_lump;rpl_lump=rpl_lump->next)
231                 len+=rpl_lump->text.len;
232
233         p=(char *)shm_malloc(len);foo=p;
234         if (!p)
235         {
236                 LOG(L_ERR , "ERROR: sip_msg_cloner: cannot allocate memory\n" );
237                 return 0;
238         }
239
240         /* filling up the new structure */
241         new_msg = (struct sip_msg*)p;
242         /* sip msg structure */
243         memcpy( new_msg , org_msg , sizeof(struct sip_msg) );
244         p += ROUND4(sizeof(struct sip_msg));
245         new_msg->add_rm = new_msg->repl_add_rm = 0;
246         /* new_uri */
247         if (org_msg->new_uri.s && org_msg->new_uri.len)
248         {
249                 new_msg->new_uri.s = p;
250                 memcpy( p , org_msg->new_uri.s , org_msg->new_uri.len);
251                 p += ROUND4(org_msg->new_uri.len);
252         }
253         /* message buffers(org and scratch pad) */
254         memcpy( p , org_msg->orig , org_msg->len);
255         /* ZT to be safer */
256         *(p+org_msg->len)=0;
257         new_msg->orig = new_msg->buf = p;
258         p += ROUND4(new_msg->len+1);
259         /* unparsed and eoh pointer */
260         new_msg->unparsed = translate_pointer(new_msg->buf ,org_msg->buf,
261                 org_msg->unparsed );
262         new_msg->eoh = translate_pointer(new_msg->buf,org_msg->buf,org_msg->eoh);
263         /* first line, updating the pointers*/
264         if ( org_msg->first_line.type==SIP_REQUEST )
265         {
266                 new_msg->first_line.u.request.method.s =
267                         translate_pointer( new_msg->buf , org_msg->buf ,
268                         org_msg->first_line.u.request.method.s );
269                 new_msg->first_line.u.request.uri.s =
270                         translate_pointer( new_msg->buf , org_msg->buf ,
271                         org_msg->first_line.u.request.uri.s );
272                 new_msg->first_line.u.request.version.s =
273                         translate_pointer( new_msg->buf , org_msg->buf ,
274                         org_msg->first_line.u.request.version.s );
275         }
276         else if ( org_msg->first_line.type==SIP_REPLY )
277         {
278                 new_msg->first_line.u.reply.version.s =
279                         translate_pointer( new_msg->buf , org_msg->buf ,
280                         org_msg->first_line.u.reply.version.s );
281                 new_msg->first_line.u.reply.status.s =
282                         translate_pointer( new_msg->buf , org_msg->buf ,
283                         org_msg->first_line.u.reply.status.s );
284                 new_msg->first_line.u.reply.reason.s =
285                         translate_pointer( new_msg->buf , org_msg->buf ,
286                         org_msg->first_line.u.reply.reason.s );
287         }
288
289         /*headers list*/
290         new_msg->via1=0;
291         new_msg->via2=0;
292         for( hdr=org_msg->headers,last_hdr=0 ; hdr ; hdr=hdr->next )
293         {
294                 new_hdr = (struct hdr_field*)p;
295                 memcpy(new_hdr, hdr, sizeof(struct hdr_field) );
296                 p += ROUND4(sizeof( struct hdr_field));
297                 new_hdr->name.s = translate_pointer(new_msg->buf, org_msg->buf,
298                         hdr->name.s);
299                 new_hdr->body.s = translate_pointer(new_msg->buf, org_msg->buf,
300                         hdr->body.s);
301                 /* by default, we assume we don't understand this header in TM
302                    and better set it to zero; if we do, we will set a specific
303                    valu in the following switch statement
304                 */
305                 new_hdr->parsed=0;
306
307                 switch (hdr->type)
308                 {
309                         case HDR_VIA:
310                                 /*fprintf(stderr,"prepare to clone via |%.*s|\n",
311                                         via_len((struct via_body*)hdr->parsed),
312                                         via_s((struct via_body*)hdr->parsed,org_msg));*/
313                                 if ( !new_msg->via1 )
314                                 {
315                                         new_msg->h_via1 = new_hdr;
316                                         new_msg->via1 = via_body_cloner(new_msg->buf,
317                                                 org_msg->buf, (struct via_body*)hdr->parsed, &p);
318                                         new_hdr->parsed  = (void*)new_msg->via1;
319                                         /*fprintf(stderr,"setting via1 |%.*s|\n",
320                                                 via_len(new_msg->via1),
321                                                 via_s(new_msg->via1,new_msg));*/
322                                         if ( new_msg->via1->next )
323                                                 new_msg->via2 = new_msg->via1->next;
324                                 }
325                                 else if ( !new_msg->via2 && new_msg->via1 )
326                                 {
327                                         new_msg->h_via2 = new_hdr;
328                                         if ( new_msg->via1->next )
329                                                 new_hdr->parsed = (void*)new_msg->via1->next;
330                                         else{
331                                                 new_msg->via2 = via_body_cloner( new_msg->buf,
332                                                         org_msg->buf, (struct via_body*)hdr->parsed, &p);
333                                                 new_hdr->parsed  = (void*)new_msg->via2;
334                                         }
335                                 }
336                                 else if ( new_msg->via2 && new_msg->via1 )
337                                 {
338                                         new_hdr->parsed =  
339                                                 via_body_cloner( new_msg->buf , org_msg->buf ,
340                                                 (struct via_body*)hdr->parsed , &p);
341                                 }
342                 /*fprintf(stderr," via1 is |%.*s|\n",
343                         via_len(new_msg->via1),
344                         via_s(new_msg->via1,new_msg));*/
345   
346                                 break;
347                         case HDR_CSEQ:
348                                 new_hdr->parsed = p;
349                                 p +=ROUND4(sizeof(struct cseq_body));
350                                 memcpy(new_hdr->parsed, hdr->parsed, sizeof(struct cseq_body));
351                                 ((struct cseq_body*)new_hdr->parsed)->number.s =
352                                         translate_pointer(new_msg->buf ,org_msg->buf,
353                                         ((struct cseq_body*)hdr->parsed)->number.s );
354                                 ((struct cseq_body*)new_hdr->parsed)->method.s =
355                                         translate_pointer(new_msg->buf ,org_msg->buf,
356                                         ((struct cseq_body*)hdr->parsed)->method.s );
357                                 new_msg->cseq = new_hdr;
358                                 break;
359                         case HDR_TO:
360                                 new_hdr->parsed = p;
361                                 p +=ROUND4(sizeof(struct to_body));
362                                 memcpy(new_hdr->parsed, hdr->parsed, sizeof(struct to_body));
363                                 ((struct to_body*)new_hdr->parsed)->body.s =
364                                         translate_pointer( new_msg->buf , org_msg->buf ,
365                                         ((struct to_body*)hdr->parsed)->body.s );
366                                 ((struct to_body*)new_hdr->parsed)->uri.s =
367                                         translate_pointer( new_msg->buf , org_msg->buf ,
368                                         ((struct to_body*)hdr->parsed)->uri.s );
369                                 if ( ((struct to_body*)hdr->parsed)->tag_value.s )
370                                         ((struct to_body*)new_hdr->parsed)->tag_value.s =
371                                                 translate_pointer( new_msg->buf , org_msg->buf ,
372                                                 ((struct to_body*)hdr->parsed)->tag_value.s );
373                                 /*to params*/
374                                 to_prm = ((struct to_body*)(hdr->parsed))->param_lst;
375                                 for(;to_prm;to_prm=to_prm->next)
376                                 {
377                                         /*alloc*/
378                                         new_to_prm = (struct to_param*)p;
379                                         p +=ROUND4(sizeof(struct to_param ));
380                                         /*coping*/
381                                         memcpy( new_to_prm, to_prm, sizeof(struct to_param ));
382                                         ((struct to_body*)new_hdr->parsed)->param_lst = 0;
383                                         new_to_prm->name.s = translate_pointer( new_msg->buf,
384                                                 org_msg->buf , to_prm->name.s );
385                                         new_to_prm->value.s = translate_pointer( new_msg->buf,
386                                                 org_msg->buf , to_prm->value.s );
387                                         /*linking*/
388                                         if ( !((struct to_body*)new_hdr->parsed)->param_lst )
389                                                 ((struct to_body*)new_hdr->parsed)->param_lst
390                                                         = new_to_prm;
391                                         else
392                                                 ((struct to_body*)new_hdr->parsed)->last_param->next
393                                                         = new_to_prm;
394                                         ((struct to_body*)new_hdr->parsed)->last_param
395                                                 = new_to_prm;
396                                 }
397                                 new_msg->to = new_hdr;
398                                 break;
399                         case HDR_CALLID:
400                                 new_msg->callid = new_hdr;
401                                 break;
402                         case HDR_FROM:
403                                 new_msg->from = new_hdr;
404                                 break;
405                         case HDR_CONTACT:
406                                 new_msg->contact = new_hdr;
407                                 break;
408                         case HDR_MAXFORWARDS :
409                                 new_msg->maxforwards = new_hdr;
410                                 break;
411                         case HDR_ROUTE :
412                                 new_msg->route = new_hdr;
413                                 break;
414                         case HDR_RECORDROUTE :
415                                 new_msg->record_route = new_hdr;
416                                 break;
417                         case HDR_CONTENTTYPE :
418                                 new_msg->content_type = new_hdr;
419                                 break;
420                         case HDR_CONTENTLENGTH :
421                                 new_msg->content_length = new_hdr;
422                                 break;
423                         case HDR_AUTHORIZATION :
424                                 new_msg->authorization = new_hdr;
425                                 break;
426                         case HDR_EXPIRES :
427                                 new_msg->expires = new_hdr;
428                                 break;
429                         case HDR_PROXYAUTH :
430                                 new_msg->proxy_auth = new_hdr;
431                                 break;
432                         case HDR_WWWAUTH :
433                                 new_msg->www_auth = new_hdr;
434                                 break;
435                         case HDR_SUPPORTED :
436                                 new_msg->supported = new_hdr;
437                                 break;
438                         case HDR_REQUIRE :
439                                 new_msg->require = new_hdr;
440                                 break;
441                         case HDR_PROXYREQUIRE :
442                                 new_msg->proxy_require = new_hdr;
443                                 break;
444                         case HDR_UNSUPPORTED :
445                                 new_msg->unsupported = new_hdr;
446                                 break;
447                         case HDR_ALLOW :
448                                 new_msg->unsupported = new_hdr; 
449                                 break;
450                 }/*switch*/
451
452                 if ( last_hdr )
453                 {
454                         last_hdr->next = new_hdr;
455                         last_hdr=last_hdr->next;
456                 }
457                 else
458                 {
459                         last_hdr=new_hdr;
460                         new_msg->headers =new_hdr;
461                 }
462                 last_hdr->next = 0;
463                 new_msg->last_header = last_hdr;
464         }
465
466         /* clonning data lump */
467         if (org_msg->first_line.type==SIP_REQUEST) {
468                 lump_chain = org_msg->add_rm;
469                 lump_anchor = &(new_msg->add_rm);
470         }else{
471                 lump_chain = org_msg->repl_add_rm;
472                 lump_anchor = &(new_msg->repl_add_rm);
473         }
474         while (lump_chain)
475         {
476                 lump_clone( (*lump_anchor) , lump_chain , p );
477                 /*before list*/
478                 lump_tmp = lump_chain->before;
479                 lump_anchor2 = &((*lump_anchor)->before);
480                 while ( lump_tmp )
481                 {
482                         lump_clone( (*lump_anchor2) , lump_tmp , p );
483                         lump_anchor2 = &((*lump_anchor2)->before);
484                         lump_tmp = lump_tmp->before;
485                 }
486                 /*after list*/
487                 lump_tmp = lump_chain->after;
488                 lump_anchor2 = &((*lump_anchor)->after);
489                 while ( lump_tmp )
490                 {
491                         lump_clone( (*lump_anchor2) , lump_tmp , p );
492                         lump_anchor2 = &((*lump_anchor2)->after);
493                         lump_tmp = lump_tmp->after;
494                 }
495                 lump_anchor = &((*lump_anchor)->next);
496                 lump_chain = lump_chain->next;
497         }
498
499         /*cloning reply lump structures*/
500         rpl_lump_anchor = &(new_msg->reply_lump);
501         for(rpl_lump=org_msg->reply_lump;rpl_lump;rpl_lump=rpl_lump->next)
502         {
503                 *(rpl_lump_anchor)=(struct lump_rpl*)p;
504                 p+=sizeof( struct lump_rpl );
505                 (*rpl_lump_anchor)->text.len = rpl_lump->text.len;
506                 (*rpl_lump_anchor)->text.s=p;
507                 p+=rpl_lump->text.len;
508                 memcpy((*rpl_lump_anchor)->text.s,rpl_lump->text.s,rpl_lump->text.len);
509                 (*rpl_lump_anchor)->next=0;
510                 rpl_lump_anchor = &((*rpl_lump_anchor)->next);
511         }
512
513         return new_msg;
514 }
515
516
517
518
519