979e46ff9347e2b5040d7437fc7ebe96330f3c61
[sip-router] / sip_msg_clone.c
1 /* 
2  * $Id$
3  * 
4  * Copyright (C) 2009 iptelorg GmbH
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 /*
19  * sip_msg_clone.c - moved sip msg clone-in-shm functions from tm
20  */
21 /*
22  * History:
23  * --------
24  *  2009-07-22  initial version: functions moved from tm/sip_msg.c (andrei)
25 */
26
27 #include "sip_msg_clone.h"
28
29
30 #include "dprint.h"
31 #include "mem/mem.h"
32 #include "data_lump.h"
33 #include "data_lump_rpl.h"
34 #include "ut.h"
35 #include "parser/digest/digest.h"
36 #include "parser/parse_to.h"
37 #include "atomic_ops.h"
38
39 /* rounds to the first 4 byte multiple on 32 bit archs
40  * and to the first 8 byte multiple on 64 bit archs */
41 #define ROUND4(s) \
42         (((s)+(sizeof(char*)-1))&(~(sizeof(char*)-1)))
43
44 #define lump_len( _lump) \
45         (ROUND4(sizeof(struct lump)) +\
46         ROUND4(((_lump)->op==LUMP_ADD)?(_lump)->len:0))
47 #define lump_clone( _new,_old,_ptr) \
48         {\
49                 (_new) = (struct lump*)(_ptr);\
50                 memcpy( (_new), (_old), sizeof(struct lump) );\
51                 (_new)->flags|=LUMPFLAG_SHMEM; \
52                 (_ptr)+=ROUND4(sizeof(struct lump));\
53                 if ( (_old)->op==LUMP_ADD) {\
54                         (_new)->u.value = (char*)(_ptr);\
55                         memcpy( (_new)->u.value , (_old)->u.value , (_old)->len);\
56                         (_ptr)+=ROUND4((_old)->len);}\
57         }
58
59 /* length of the data lump structures */
60 #define LUMP_LIST_LEN(len, list) \
61 do { \
62         struct lump* tmp, *chain; \
63         chain = (list); \
64         while (chain) \
65         { \
66                 (len) += lump_len(chain); \
67                 tmp = chain->before; \
68                 while ( tmp ) \
69                 { \
70                         (len) += lump_len( tmp ); \
71                         tmp = tmp->before; \
72                 } \
73                 tmp = chain->after; \
74                 while ( tmp ) \
75                 { \
76                         (len) += lump_len( tmp ); \
77                         tmp = tmp->after; \
78                 } \
79                 chain = chain->next; \
80         } \
81 } while(0);
82
83 /* length of the reply lump structure */
84 #define RPL_LUMP_LIST_LEN(len, list) \
85 do { \
86         struct lump_rpl* rpl_lump; \
87         for(rpl_lump=(list);rpl_lump;rpl_lump=rpl_lump->next) \
88                 (len)+=ROUND4(sizeof(struct lump_rpl))+ROUND4(rpl_lump->text.len); \
89 } while(0);
90
91 /* clones data lumps */
92 #define CLONE_LUMP_LIST(anchor, list, _ptr) \
93 do { \
94         struct lump* lump_tmp, *l; \
95         struct lump** lump_anchor2, **a; \
96         a = (anchor); \
97         l = (list); \
98         while (l) \
99         { \
100                 lump_clone( (*a) , l , (_ptr) ); \
101                 /*before list*/ \
102                 lump_tmp = l->before; \
103                 lump_anchor2 = &((*a)->before); \
104                 while ( lump_tmp ) \
105                 { \
106                         lump_clone( (*lump_anchor2) , lump_tmp , (_ptr) ); \
107                         lump_anchor2 = &((*lump_anchor2)->before); \
108                         lump_tmp = lump_tmp->before; \
109                 } \
110                 /*after list*/ \
111                 lump_tmp = l->after; \
112                 lump_anchor2 = &((*a)->after); \
113                 while ( lump_tmp ) \
114                 { \
115                         lump_clone( (*lump_anchor2) , lump_tmp , (_ptr) ); \
116                         lump_anchor2 = &((*lump_anchor2)->after); \
117                         lump_tmp = lump_tmp->after; \
118                 } \
119                 a = &((*a)->next); \
120                 l = l->next; \
121         } \
122 } while(0)
123
124 /* clones reply lumps */
125 #define CLONE_RPL_LUMP_LIST(anchor, list, _ptr) \
126 do { \
127         struct lump_rpl* rpl_lump; \
128         struct lump_rpl** rpl_lump_anchor; \
129         rpl_lump_anchor = (anchor); \
130         for(rpl_lump=(list);rpl_lump;rpl_lump=rpl_lump->next) \
131         { \
132                 *(rpl_lump_anchor)=(struct lump_rpl*)(_ptr); \
133                 (_ptr)+=ROUND4(sizeof( struct lump_rpl )); \
134                 (*rpl_lump_anchor)->flags = LUMP_RPL_SHMEM | \
135                         (rpl_lump->flags&(~(LUMP_RPL_NODUP|LUMP_RPL_NOFREE))); \
136                 (*rpl_lump_anchor)->text.len = rpl_lump->text.len; \
137                 (*rpl_lump_anchor)->text.s=(_ptr); \
138                 (_ptr)+=ROUND4(rpl_lump->text.len); \
139                 memcpy((*rpl_lump_anchor)->text.s,rpl_lump->text.s,rpl_lump->text.len); \
140                 (*rpl_lump_anchor)->next=0; \
141                 rpl_lump_anchor = &((*rpl_lump_anchor)->next); \
142         } \
143 } while (0)
144
145
146
147 inline struct via_body* via_body_cloner( char* new_buf,
148                                         char *org_buf, struct via_body *param_org_via, char **p)
149 {
150         struct via_body *new_via;
151         struct via_body *first_via, *last_via;
152         struct via_body *org_via;
153
154         first_via = last_via = 0;
155         org_via = param_org_via;
156
157         do
158         {
159                 /* clones the via_body structure */
160                 new_via = (struct via_body*)(*p);
161                 memcpy( new_via , org_via , sizeof( struct via_body) );
162                 (*p) += ROUND4(sizeof( struct via_body ));
163
164                 /* hdr (str type) */
165                 new_via->hdr.s=translate_pointer(new_buf,org_buf,org_via->hdr.s);
166                 /* name (str type) */
167                 new_via->name.s=translate_pointer(new_buf,org_buf,org_via->name.s);
168                 /* version (str type) */
169                 new_via->version.s=
170                         translate_pointer(new_buf,org_buf,org_via->version.s);
171                 /* transport (str type) */
172                 new_via->transport.s=
173                         translate_pointer(new_buf,org_buf,org_via->transport.s);
174                 /* host (str type) */
175                 new_via->host.s=translate_pointer(new_buf,org_buf,org_via->host.s);
176                 /* port_str (str type) */
177                 new_via->port_str.s=
178                         translate_pointer(new_buf,org_buf,org_via->port_str.s);
179                 /* params (str type) */
180                 new_via->params.s=translate_pointer(new_buf,org_buf,org_via->params.s);
181                 /* transaction id */
182                 new_via->tid.s=
183                         translate_pointer(new_buf, org_buf, org_via->tid.s);
184                 /* comment (str type) */
185                 new_via->comment.s=
186                         translate_pointer(new_buf,org_buf,org_via->comment.s);
187
188                 if ( org_via->param_lst )
189                 {
190                         struct via_param *vp, *new_vp, *last_new_vp;
191                         for( vp=org_via->param_lst, last_new_vp=0 ; vp ; vp=vp->next )
192                         {
193                                 new_vp = (struct via_param*)(*p);
194                                 memcpy( new_vp , vp , sizeof(struct via_param));
195                                 (*p) += ROUND4(sizeof(struct via_param));
196                                 new_vp->name.s=translate_pointer(new_buf,org_buf,vp->name.s);
197                                 new_vp->value.s=translate_pointer(new_buf,org_buf,vp->value.s);
198                                 new_vp->start=translate_pointer(new_buf,org_buf,vp->start);
199
200                                 /* "translate" the shortcuts */
201                                 switch(new_vp->type){
202                                         case PARAM_BRANCH:
203                                                         new_via->branch = new_vp;
204                                                         break;
205                                         case PARAM_RECEIVED:
206                                                         new_via->received = new_vp;
207                                                         break;
208                                         case PARAM_RPORT:
209                                                         new_via->rport = new_vp;
210                                                         break;
211                                         case PARAM_I:
212                                                         new_via->i = new_vp;
213                                                         break;
214                                         case PARAM_ALIAS:
215                                                         new_via->alias = new_vp;
216                                                         break;
217
218 #ifdef USE_COMP
219                                         case PARAM_COMP:
220                                                         new_via->comp = new_vp;
221                                                         break;
222 #endif
223                                 }
224
225                                 if (last_new_vp)
226                                         last_new_vp->next = new_vp;
227                                 else
228                                         new_via->param_lst = new_vp;
229
230                                 last_new_vp = new_vp;
231                                 last_new_vp->next = NULL;
232                         }
233                         new_via->last_param = new_vp;
234                 }/*end if via has params */
235
236                 if (last_via)
237                         last_via->next = new_via;
238                 else
239                         first_via = new_via;
240                 last_via = new_via;
241                 org_via = org_via->next;
242         }while(org_via);
243
244         return first_via;
245 }
246
247
248 static void uri_trans(char *new_buf, char *org_buf, struct sip_uri *uri)
249 {
250         uri->user.s=translate_pointer(new_buf,org_buf,uri->user.s);
251         uri->passwd.s=translate_pointer(new_buf,org_buf,uri->passwd.s);
252         uri->host.s=translate_pointer(new_buf,org_buf,uri->host.s);
253         uri->port.s=translate_pointer(new_buf,org_buf,uri->port.s);
254         uri->params.s=translate_pointer(new_buf,org_buf,uri->params.s);
255         uri->headers.s=translate_pointer(new_buf,org_buf,uri->headers.s);
256         /* parameters */
257         uri->transport.s=translate_pointer(new_buf,org_buf,uri->transport.s);
258         uri->ttl.s=translate_pointer(new_buf,org_buf,uri->ttl.s);
259         uri->user_param.s=translate_pointer(new_buf,org_buf,uri->user_param.s);
260         uri->maddr.s=translate_pointer(new_buf,org_buf,uri->maddr.s);
261         uri->method.s=translate_pointer(new_buf,org_buf,uri->method.s);
262         uri->lr.s=translate_pointer(new_buf,org_buf,uri->lr.s);
263         uri->r2.s=translate_pointer(new_buf,org_buf,uri->r2.s);
264         /* values */
265         uri->transport_val.s
266                 =translate_pointer(new_buf,org_buf,uri->transport_val.s);
267         uri->ttl_val.s=translate_pointer(new_buf,org_buf,uri->ttl_val.s);
268         uri->user_param_val.s
269                 =translate_pointer(new_buf,org_buf,uri->user_param_val.s);
270         uri->maddr_val.s=translate_pointer(new_buf,org_buf,uri->maddr_val.s);
271         uri->method_val.s=translate_pointer(new_buf,org_buf,uri->method_val.s);
272         uri->lr_val.s=translate_pointer(new_buf,org_buf,uri->lr_val.s);
273         uri->r2_val.s=translate_pointer(new_buf,org_buf,uri->r2_val.s);
274 }
275
276
277 static inline struct auth_body* auth_body_cloner(char* new_buf, char *org_buf, struct auth_body *auth, char **p)
278 {
279         struct auth_body* new_auth;
280
281         new_auth = (struct auth_body*)(*p);
282         memcpy(new_auth , auth , sizeof(struct auth_body));
283         (*p) += ROUND4(sizeof(struct auth_body));
284
285         /* authorized field must be cloned elsewhere */
286         new_auth->digest.username.whole.s =
287                 translate_pointer(new_buf, org_buf, auth->digest.username.whole.s);
288         new_auth->digest.username.user.s =
289                 translate_pointer(new_buf, org_buf, auth->digest.username.user.s);
290         new_auth->digest.username.domain.s =
291                 translate_pointer(new_buf, org_buf, auth->digest.username.domain.s);
292         new_auth->digest.realm.s =
293                 translate_pointer(new_buf, org_buf, auth->digest.realm.s);
294         new_auth->digest.nonce.s =
295                 translate_pointer(new_buf, org_buf, auth->digest.nonce.s);
296         new_auth->digest.uri.s =
297                 translate_pointer(new_buf, org_buf, auth->digest.uri.s);
298         new_auth->digest.response.s =
299                 translate_pointer(new_buf, org_buf, auth->digest.response.s);
300         new_auth->digest.alg.alg_str.s =
301                 translate_pointer(new_buf, org_buf, auth->digest.alg.alg_str.s);
302         new_auth->digest.cnonce.s =
303                 translate_pointer(new_buf, org_buf, auth->digest.cnonce.s);
304         new_auth->digest.opaque.s =
305                 translate_pointer(new_buf, org_buf, auth->digest.opaque.s);
306         new_auth->digest.qop.qop_str.s =
307                 translate_pointer(new_buf, org_buf, auth->digest.qop.qop_str.s);
308         new_auth->digest.nc.s =
309                 translate_pointer(new_buf, org_buf, auth->digest.nc.s);
310         return new_auth;
311 }
312
313
314 static inline int clone_authorized_hooks(struct sip_msg* new,
315                                          struct sip_msg* old)
316 {
317         struct hdr_field* ptr, *new_ptr, *hook1, *hook2;
318         char stop = 0;
319
320         get_authorized_cred(old->authorization, &hook1);
321         if (!hook1) stop = 1;
322
323         get_authorized_cred(old->proxy_auth, &hook2);
324         if (!hook2) stop |= 2;
325
326         ptr = old->headers;
327         new_ptr = new->headers;
328
329         while(ptr) {
330                 if (ptr == hook1) {
331                         if (!new->authorization || !new->authorization->parsed) {
332                                 LOG(L_CRIT, "BUG: Error in message cloner (authorization)\n");
333                                 return -1;
334                         }
335                         ((struct auth_body*)new->authorization->parsed)->authorized =
336                                 new_ptr;
337                         stop |= 1;
338                 }
339
340                 if (ptr == hook2) {
341                         if (!new->proxy_auth || !new->proxy_auth->parsed) {
342                                 LOG(L_CRIT, "BUG: Error in message cloner (proxy_auth)\n");
343                                 return -1;
344                         }
345                         ((struct auth_body*)new->proxy_auth->parsed)->authorized =
346                                 new_ptr;
347                         stop |= 2;
348                 }
349
350                 if (stop == 3) break;
351
352                 ptr = ptr->next;
353                 new_ptr = new_ptr->next;
354         }
355         return 0;
356 }
357
358
359 #define AUTH_BODY_SIZE sizeof(struct auth_body)
360
361 #define HOOK_SET(hook) (new_msg->hook != org_msg->hook)
362
363
364
365 /** Creates a shm clone for a sip_msg.
366  * org_msg is cloned along with most of its headers and lumps into one
367  * shm memory block (so that a shm_free() on the result will free everything)
368  * @return shm malloced sip_msg on success, 0 on error
369  * Warning: Cloner does not clone all hdr_field headers (From, To, etc.).
370  */
371 struct sip_msg*  sip_msg_shm_clone( struct sip_msg *org_msg, int *sip_msg_len,
372                                                                         int clone_lumps)
373 {
374         unsigned int      len;
375         struct hdr_field  *hdr,*new_hdr,*last_hdr;
376         struct via_body   *via;
377         struct via_param  *prm;
378         struct to_param   *to_prm,*new_to_prm;
379         struct sip_msg    *new_msg;
380         char              *p;
381
382         /*computing the length of entire sip_msg structure*/
383         len = ROUND4(sizeof( struct sip_msg ));
384         /*we will keep only the original msg +ZT */
385         len += ROUND4(org_msg->len + 1);
386         /*the new uri (if any)*/
387         if (org_msg->new_uri.s && org_msg->new_uri.len)
388                 len+= ROUND4(org_msg->new_uri.len);
389         /*the dst uri (if any)*/
390         if (org_msg->dst_uri.s && org_msg->dst_uri.len)
391                 len+= ROUND4(org_msg->dst_uri.len);
392         /*all the headers*/
393         for( hdr=org_msg->headers ; hdr ; hdr=hdr->next )
394         {
395                 /*size of header struct*/
396                 len += ROUND4(sizeof( struct hdr_field));
397                 switch (hdr->type) {
398                              /* Safely ignore auxiliary header types */
399                 case HDR_ERROR_T:
400                 case HDR_OTHER_T:
401                 case HDR_VIA2_T:
402                 case HDR_EOH_T:
403                         break;
404
405                 case HDR_VIA_T:
406                         for (via=(struct via_body*)hdr->parsed;via;via=via->next) {
407                                 len+=ROUND4(sizeof(struct via_body));
408                                      /*via param*/
409                                 for(prm=via->param_lst;prm;prm=prm->next)
410                                         len+=ROUND4(sizeof(struct via_param ));
411                         }
412                         break;
413
414                 case HDR_TO_T:
415                 case HDR_FROM_T:
416                              /* From header might be unparsed */
417                         if (hdr->parsed) {
418                                 len+=ROUND4(sizeof(struct to_body));
419                                      /*to param*/
420                                 to_prm = ((struct to_body*)(hdr->parsed))->param_lst;
421                                 for(;to_prm;to_prm=to_prm->next)
422                                         len+=ROUND4(sizeof(struct to_param ));
423                         }
424                         break;
425
426                 case HDR_CSEQ_T:
427                         len+=ROUND4(sizeof(struct cseq_body));
428                         break;
429
430
431                 case HDR_AUTHORIZATION_T:
432                 case HDR_PROXYAUTH_T:
433                         if (hdr->parsed) {
434                                 len += ROUND4(AUTH_BODY_SIZE);
435                         }
436                         break;
437
438                 case HDR_CALLID_T:
439                 case HDR_CONTACT_T:
440                 case HDR_MAXFORWARDS_T:
441                 case HDR_ROUTE_T:
442                 case HDR_RECORDROUTE_T:
443                 case HDR_CONTENTTYPE_T:
444                 case HDR_CONTENTLENGTH_T:
445                 case HDR_RETRY_AFTER_T:
446                 case HDR_EXPIRES_T:
447                 case HDR_SUPPORTED_T:
448                 case HDR_REQUIRE_T:
449                 case HDR_PROXYREQUIRE_T:
450                 case HDR_UNSUPPORTED_T:
451                 case HDR_ALLOW_T:
452                 case HDR_EVENT_T:
453                 case HDR_ACCEPT_T:
454                 case HDR_ACCEPTLANGUAGE_T:
455                 case HDR_ORGANIZATION_T:
456                 case HDR_PRIORITY_T:
457                 case HDR_SUBJECT_T:
458                 case HDR_USERAGENT_T:
459                 case HDR_SERVER_T:
460                 case HDR_ACCEPTDISPOSITION_T:
461                 case HDR_CONTENTDISPOSITION_T:
462                 case HDR_DIVERSION_T:
463                 case HDR_RPID_T:
464                 case HDR_REFER_TO_T:
465                 case HDR_SIPIFMATCH_T:
466                 case HDR_SESSIONEXPIRES_T:
467                 case HDR_MIN_SE_T:
468                 case HDR_SUBSCRIPTION_STATE_T:
469                 case HDR_ACCEPTCONTACT_T:
470                 case HDR_ALLOWEVENTS_T:
471                 case HDR_CONTENTENCODING_T:
472                 case HDR_REFERREDBY_T:
473                 case HDR_REJECTCONTACT_T:
474                 case HDR_REQUESTDISPOSITION_T:
475                 case HDR_WWW_AUTHENTICATE_T:
476                 case HDR_PROXY_AUTHENTICATE_T:
477                 case HDR_DATE_T:
478                 case HDR_IDENTITY_T:
479                 case HDR_IDENTITY_INFO_T:
480                 case HDR_PPI_T:
481                 case HDR_PAI_T:
482                 case HDR_PATH_T:
483                 case HDR_PRIVACY_T:
484                         /* we ignore them for now even if they have something parsed*/
485                         break;
486                 }/*switch*/
487         }/*for all headers*/
488         
489         if (clone_lumps) {
490                 /* calculate the length of the data and reply lump structures */
491                 LUMP_LIST_LEN(len, org_msg->add_rm);
492                 LUMP_LIST_LEN(len, org_msg->body_lumps);
493                 RPL_LUMP_LIST_LEN(len, org_msg->reply_lump);
494         }
495         
496         p=(char *)shm_malloc(len);
497         if (!p)
498         {
499                 LOG(L_ERR , "ERROR: sip_msg_cloner: cannot allocate memory\n" );
500                 return 0;
501         }
502         if (sip_msg_len)
503                 *sip_msg_len = len;
504
505         /* filling up the new structure */
506         new_msg = (struct sip_msg*)p;
507         /* sip msg structure */
508         memcpy( new_msg , org_msg , sizeof(struct sip_msg) );
509
510         new_msg->msg_flags |= FL_SHM_CLONE;
511         p += ROUND4(sizeof(struct sip_msg));
512         new_msg->body = 0;
513         new_msg->add_rm = 0;
514         new_msg->body_lumps = 0;
515         new_msg->reply_lump = 0;
516         /* new_uri */
517         if (org_msg->new_uri.s && org_msg->new_uri.len)
518         {
519                 new_msg->new_uri.s = p;
520                 memcpy( p , org_msg->new_uri.s , org_msg->new_uri.len);
521                 p += ROUND4(org_msg->new_uri.len);
522         }
523         /* dst_uri */
524         if (org_msg->dst_uri.s && org_msg->dst_uri.len)
525         {
526                 new_msg->dst_uri.s = p;
527                 memcpy( p , org_msg->dst_uri.s , org_msg->dst_uri.len);
528                 p += ROUND4(org_msg->dst_uri.len);
529         }
530         /* path_vec is not cloned (it's reset instead) */
531         new_msg->path_vec.s=0;
532         new_msg->path_vec.len=0;
533         /* message buffers(org and scratch pad) */
534         memcpy( p , org_msg->buf, org_msg->len);
535         /* ZT to be safer */
536         *(p+org_msg->len)=0;
537         new_msg->buf = p;
538         p += ROUND4(new_msg->len+1);
539         /* unparsed and eoh pointer */
540         new_msg->unparsed = translate_pointer(new_msg->buf ,org_msg->buf,
541                 org_msg->unparsed );
542         new_msg->eoh = translate_pointer(new_msg->buf,org_msg->buf,org_msg->eoh);
543         /* first line, updating the pointers*/
544         if ( org_msg->first_line.type==SIP_REQUEST )
545         {
546                 new_msg->first_line.u.request.method.s =
547                         translate_pointer( new_msg->buf , org_msg->buf ,
548                         org_msg->first_line.u.request.method.s );
549                 new_msg->first_line.u.request.uri.s =
550                         translate_pointer( new_msg->buf , org_msg->buf ,
551                         org_msg->first_line.u.request.uri.s );
552                 new_msg->first_line.u.request.version.s =
553                         translate_pointer( new_msg->buf , org_msg->buf ,
554                         org_msg->first_line.u.request.version.s );
555                 uri_trans(new_msg->buf, org_msg->buf, &new_msg->parsed_orig_ruri);
556                 if (org_msg->new_uri.s && org_msg->new_uri.len)
557                         uri_trans(new_msg->new_uri.s, org_msg->new_uri.s,
558                                                                                         &new_msg->parsed_uri);
559                 else
560                         uri_trans(new_msg->buf, org_msg->buf, &new_msg->parsed_uri);
561         }
562         else if ( org_msg->first_line.type==SIP_REPLY )
563         {
564                 new_msg->first_line.u.reply.version.s =
565                         translate_pointer( new_msg->buf , org_msg->buf ,
566                         org_msg->first_line.u.reply.version.s );
567                 new_msg->first_line.u.reply.status.s =
568                         translate_pointer( new_msg->buf , org_msg->buf ,
569                         org_msg->first_line.u.reply.status.s );
570                 new_msg->first_line.u.reply.reason.s =
571                         translate_pointer( new_msg->buf , org_msg->buf ,
572                         org_msg->first_line.u.reply.reason.s );
573         }
574
575        /*headers list*/
576        new_msg->via1=0;
577        new_msg->via2=0;
578
579         for( hdr=org_msg->headers,last_hdr=0 ; hdr ; hdr=hdr->next )
580         {
581                 new_hdr = (struct hdr_field*)p;
582                 memcpy(new_hdr, hdr, sizeof(struct hdr_field) );
583                 p += ROUND4(sizeof( struct hdr_field));
584                 new_hdr->name.s = translate_pointer(new_msg->buf, org_msg->buf,
585                         hdr->name.s);
586                 new_hdr->body.s = translate_pointer(new_msg->buf, org_msg->buf,
587                         hdr->body.s);
588                 /* by default, we assume we don't understand this header in TM
589                    and better set it to zero; if we do, we will set a specific
590                    value in the following switch statement
591                 */
592                 new_hdr->parsed=0;
593
594                 switch (hdr->type)
595                 {
596                              /* Ignore auxiliary header types */
597                 case HDR_ERROR_T:
598                 case HDR_OTHER_T:
599                 case HDR_VIA2_T:
600                 case HDR_EOH_T:
601                 case HDR_ACCEPTCONTACT_T:
602                 case HDR_ALLOWEVENTS_T:
603                 case HDR_CONTENTENCODING_T:
604                 case HDR_REFERREDBY_T:
605                 case HDR_REJECTCONTACT_T:
606                 case HDR_REQUESTDISPOSITION_T:
607                 case HDR_WWW_AUTHENTICATE_T:
608                 case HDR_PROXY_AUTHENTICATE_T:
609                 case HDR_DATE_T:
610                 case HDR_IDENTITY_T:
611                 case HDR_IDENTITY_INFO_T:
612                 case HDR_RETRY_AFTER_T:
613                         break;
614
615                 case HDR_VIA_T:
616                         if ( !new_msg->via1 ) {
617                                 new_msg->h_via1 = new_hdr;
618                                 new_msg->via1 = via_body_cloner(new_msg->buf,
619                                                                 org_msg->buf, (struct via_body*)hdr->parsed, &p);
620                                 new_hdr->parsed  = (void*)new_msg->via1;
621                                 if ( new_msg->via1->next ) {
622                                         new_msg->via2 = new_msg->via1->next;
623                                 }
624                         } else if ( !new_msg->via2 && new_msg->via1 ) {
625                                 new_msg->h_via2 = new_hdr;
626                                 if ( new_msg->via1->next ) {
627                                         new_hdr->parsed = (void*)new_msg->via1->next;
628                                 } else {
629                                         new_msg->via2 = via_body_cloner( new_msg->buf,
630                                                                          org_msg->buf, (struct via_body*)hdr->parsed, &p);
631                                         new_hdr->parsed  = (void*)new_msg->via2;
632                                 }
633                         } else if ( new_msg->via2 && new_msg->via1 ) {
634                                 new_hdr->parsed = via_body_cloner( new_msg->buf , org_msg->buf ,
635                                                                    (struct via_body*)hdr->parsed , &p);
636                         }
637                         break;
638                 case HDR_CSEQ_T:
639                         new_hdr->parsed = p;
640                         p +=ROUND4(sizeof(struct cseq_body));
641                         memcpy(new_hdr->parsed, hdr->parsed, sizeof(struct cseq_body));
642                         ((struct cseq_body*)new_hdr->parsed)->number.s =
643                                 translate_pointer(new_msg->buf ,org_msg->buf,
644                                                   ((struct cseq_body*)hdr->parsed)->number.s );
645                         ((struct cseq_body*)new_hdr->parsed)->method.s =
646                                 translate_pointer(new_msg->buf ,org_msg->buf,
647                                                   ((struct cseq_body*)hdr->parsed)->method.s );
648                         if (!HOOK_SET(cseq)) new_msg->cseq = new_hdr;
649                         break;
650                 case HDR_TO_T:
651                 case HDR_FROM_T:
652                         if (hdr->type == HDR_TO_T) {
653                                 if (!HOOK_SET(to)) new_msg->to = new_hdr;
654                         } else {
655                                 if (!HOOK_SET(from)) new_msg->from = new_hdr;
656                         }
657                              /* From header might be unparsed */
658                         if (!hdr->parsed) break;
659                         new_hdr->parsed = p;
660                         p +=ROUND4(sizeof(struct to_body));
661                         memcpy(new_hdr->parsed, hdr->parsed, sizeof(struct to_body));
662                         ((struct to_body*)new_hdr->parsed)->body.s =
663                                 translate_pointer( new_msg->buf , org_msg->buf ,
664                                                    ((struct to_body*)hdr->parsed)->body.s );
665                         ((struct to_body*)new_hdr->parsed)->display.s =
666                                 translate_pointer( new_msg->buf, org_msg->buf,
667                                                    ((struct to_body*)hdr->parsed)->display.s);
668                         ((struct to_body*)new_hdr->parsed)->uri.s =
669                                 translate_pointer( new_msg->buf , org_msg->buf ,
670                                                    ((struct to_body*)hdr->parsed)->uri.s );
671                         if ( ((struct to_body*)hdr->parsed)->tag_value.s )
672                                 ((struct to_body*)new_hdr->parsed)->tag_value.s =
673                                         translate_pointer( new_msg->buf , org_msg->buf ,
674                                                            ((struct to_body*)hdr->parsed)->tag_value.s );
675                         if ( (((struct to_body*)new_hdr->parsed)->parsed_uri.user.s)
676                                 || (((struct to_body*)new_hdr->parsed)->parsed_uri.host.s) )
677                                         uri_trans(new_msg->buf, org_msg->buf,
678                                                         &((struct to_body*)new_hdr->parsed)->parsed_uri);
679                              /*to params*/
680                         to_prm = ((struct to_body*)(hdr->parsed))->param_lst;
681                         for(;to_prm;to_prm=to_prm->next) {
682                                      /*alloc*/
683                                 new_to_prm = (struct to_param*)p;
684                                 p +=ROUND4(sizeof(struct to_param ));
685                                      /*coping*/
686                                 memcpy( new_to_prm, to_prm, sizeof(struct to_param ));
687                                 ((struct to_body*)new_hdr->parsed)->param_lst = 0;
688                                 new_to_prm->name.s = translate_pointer( new_msg->buf,
689                                                                         org_msg->buf , to_prm->name.s );
690                                 new_to_prm->value.s = translate_pointer( new_msg->buf,
691                                                                          org_msg->buf , to_prm->value.s );
692                                      /*linking*/
693                                 if ( !((struct to_body*)new_hdr->parsed)->param_lst )
694                                         ((struct to_body*)new_hdr->parsed)->param_lst
695                                                 = new_to_prm;
696                                 else
697                                         ((struct to_body*)new_hdr->parsed)->last_param->next
698                                                 = new_to_prm;
699                                 ((struct to_body*)new_hdr->parsed)->last_param
700                                         = new_to_prm;
701                         }
702                         break;
703                 case HDR_CALLID_T:
704                         if (!HOOK_SET(callid)) {
705                                 new_msg->callid = new_hdr;
706                         }
707                         break;
708                 case HDR_CONTACT_T:
709                         if (!HOOK_SET(contact)) {
710                                 new_msg->contact = new_hdr;
711                         }
712                         break;
713                 case HDR_MAXFORWARDS_T:
714                         if (!HOOK_SET(maxforwards)) {
715                                 new_msg->maxforwards = new_hdr;
716                         }
717                         break;
718                 case HDR_ROUTE_T:
719                         if (!HOOK_SET(route)) {
720                                 new_msg->route = new_hdr;
721                         }
722                         break;
723                 case HDR_RECORDROUTE_T:
724                         if (!HOOK_SET(record_route)) {
725                                 new_msg->record_route = new_hdr;
726                         }
727                         break;
728                 case HDR_CONTENTTYPE_T:
729                         if (!HOOK_SET(content_type)) {
730                                 new_msg->content_type = new_hdr;
731                                 new_msg->content_type->parsed = hdr->parsed;
732                         }
733                         break;
734                 case HDR_CONTENTLENGTH_T:
735                         if (!HOOK_SET(content_length)) {
736                                 new_msg->content_length = new_hdr;
737                                 new_msg->content_length->parsed = hdr->parsed;
738                         }
739                         break;
740                 case HDR_AUTHORIZATION_T:
741                         if (!HOOK_SET(authorization)) {
742                                 new_msg->authorization = new_hdr;
743                         }
744                         if (hdr->parsed) {
745                                 new_hdr->parsed = auth_body_cloner(new_msg->buf ,
746                                                                    org_msg->buf , (struct auth_body*)hdr->parsed , &p);
747                         }
748                         break;
749                 case HDR_EXPIRES_T:
750                         if (!HOOK_SET(expires)) {
751                                 new_msg->expires = new_hdr;
752                         }
753                         break;
754                 case HDR_PROXYAUTH_T:
755                         if (!HOOK_SET(proxy_auth)) {
756                                 new_msg->proxy_auth = new_hdr;
757                         }
758                         if (hdr->parsed) {
759                                 new_hdr->parsed = auth_body_cloner(new_msg->buf ,
760                                                                    org_msg->buf , (struct auth_body*)hdr->parsed , &p);
761                         }
762                         break;
763                 case HDR_SUPPORTED_T:
764                         if (!HOOK_SET(supported)) {
765                                 new_msg->supported = new_hdr;
766                         }
767                         break;
768                 case HDR_REQUIRE_T:
769                         if (!HOOK_SET(require)) {
770                                 new_msg->require = new_hdr;
771                         }
772                         break;
773                 case HDR_PROXYREQUIRE_T:
774                         if (!HOOK_SET(proxy_require)) {
775                                 new_msg->proxy_require = new_hdr;
776                         }
777                         break;
778                 case HDR_UNSUPPORTED_T:
779                         if (!HOOK_SET(unsupported)) {
780                                 new_msg->unsupported = new_hdr;
781                         }
782                         break;
783                 case HDR_ALLOW_T:
784                         if (!HOOK_SET(allow)) {
785                                 new_msg->allow = new_hdr;
786                         }
787                         break;
788                 case HDR_EVENT_T:
789                         if (!HOOK_SET(event)) {
790                                 new_msg->event = new_hdr;
791                         }
792                         break;
793                 case HDR_ACCEPT_T:
794                         if (!HOOK_SET(accept)) {
795                                 new_msg->accept = new_hdr;
796                         }
797                         break;
798                 case HDR_ACCEPTLANGUAGE_T:
799                         if (!HOOK_SET(accept_language)) {
800                                 new_msg->accept_language = new_hdr;
801                         }
802                         break;
803                 case HDR_ORGANIZATION_T:
804                         if (!HOOK_SET(organization)) {
805                                 new_msg->organization = new_hdr;
806                         }
807                         break;
808                 case HDR_PRIORITY_T:
809                         if (!HOOK_SET(priority)) {
810                                 new_msg->priority = new_hdr;
811                         }
812                         break;
813                 case HDR_SUBJECT_T:
814                         if (!HOOK_SET(subject)) {
815                                 new_msg->subject = new_hdr;
816                         }
817                         break;
818                 case HDR_USERAGENT_T:
819                         if (!HOOK_SET(user_agent)) {
820                                 new_msg->user_agent = new_hdr;
821                         }
822                         break;
823                 case HDR_SERVER_T:
824                         if (!HOOK_SET(server)) {
825                                 new_msg->server = new_hdr;
826                         }
827                         break;
828                 case HDR_ACCEPTDISPOSITION_T:
829                         if (!HOOK_SET(accept_disposition)) {
830                                 new_msg->accept_disposition = new_hdr;
831                         }
832                         break;
833                 case HDR_CONTENTDISPOSITION_T:
834                         if (!HOOK_SET(content_disposition)) {
835                                 new_msg->content_disposition = new_hdr;
836                         }
837                         break;
838                 case HDR_DIVERSION_T:
839                         if (!HOOK_SET(diversion)) {
840                                 new_msg->diversion = new_hdr;
841                         }
842                         break;
843                 case HDR_RPID_T:
844                         if (!HOOK_SET(rpid)) {
845                                 new_msg->rpid = new_hdr;
846                         }
847                         break;
848                 case HDR_REFER_TO_T:
849                         if (!HOOK_SET(refer_to)) {
850                                 new_msg->refer_to = new_hdr;
851                         }
852                         break;
853                 case HDR_SESSIONEXPIRES_T:
854                         if (!HOOK_SET(session_expires)) {
855                                 new_msg->session_expires = new_hdr;
856                         }
857                         break;
858                 case HDR_MIN_SE_T:
859                         if (!HOOK_SET(min_se)) {
860                                 new_msg->min_se = new_hdr;
861                         }
862                         break;
863                 case HDR_SUBSCRIPTION_STATE_T:
864                         if (!HOOK_SET(subscription_state)) {
865                                 new_msg->subscription_state = new_hdr;
866                         }
867                         break;
868                 case HDR_SIPIFMATCH_T:
869                         if (!HOOK_SET(sipifmatch)) {
870                                 new_msg->sipifmatch = new_hdr;
871                         }
872                         break;
873                 case HDR_PPI_T:
874                         if (!HOOK_SET(ppi)) {
875                                 new_msg->ppi = new_hdr;
876                         }
877                         break;
878                 case HDR_PAI_T:
879                         if (!HOOK_SET(pai)) {
880                                 new_msg->pai = new_hdr;
881                         }
882                         break;
883                 case HDR_PATH_T:
884                         if (!HOOK_SET(path)) {
885                                 new_msg->path = new_hdr;
886                         }
887                         break;
888                 case HDR_PRIVACY_T:
889                         if (!HOOK_SET(privacy)) {
890                                 new_msg->privacy = new_hdr;
891                         }
892                         break;
893                 }/*switch*/
894
895                 if ( last_hdr )
896                 {
897                         last_hdr->next = new_hdr;
898                         last_hdr=last_hdr->next;
899                 }
900                 else
901                 {
902                         last_hdr=new_hdr;
903                         new_msg->headers =new_hdr;
904                 }
905                 last_hdr->next = 0;
906                 new_msg->last_header = last_hdr;
907         }
908         if (clone_lumps) {
909                 /*cloning data and reply lump structures*/
910                 CLONE_LUMP_LIST(&(new_msg->add_rm), org_msg->add_rm, p);
911                 CLONE_LUMP_LIST(&(new_msg->body_lumps), org_msg->body_lumps, p);
912                 CLONE_RPL_LUMP_LIST(&(new_msg->reply_lump), org_msg->reply_lump, p);
913         }
914         
915         if (clone_authorized_hooks(new_msg, org_msg) < 0) {
916                 shm_free(new_msg);
917                 return 0;
918         }
919
920         return new_msg;
921 }
922
923
924
925 /** clones the data and reply lumps from pkg_msg to shm_msg.
926  * A new memory block is allocated for the lumps (the lumps will point
927  * into it).
928  * Note: the new memory block is linked to add_rm if
929  * at least one data lump is set, else it is linked to body_lumps
930  * if at least one body lump is set, otherwise it is linked to
931  * shm_msg->reply_lump.
932  * @param pkg_msg - sip msg whoes lumps will be cloned
933  * @param add_rm - result parameter, filled with the list of cloned
934  *                 add_rm lumps (corresp. to msg->add_rm)
935  * @param body_lumps - result parameter, filled with the list of cloned
936  *                 body lumps (corresp. to msg->body_lumps)
937  * @param reply_lump - result parameter, filled with the list of cloned
938  *                 reply lumps (corresp. to msg->reply_lump)
939  * @return 0 or 1 on success: 0 - lumps cloned), 1 - nothing to do and 
940  *         -1 on error
941  */
942 int msg_lump_cloner(struct sip_msg *pkg_msg,
943                                         struct lump** add_rm,
944                                         struct lump** body_lumps,
945                                         struct lump_rpl** reply_lump)
946 {
947         unsigned int    len;
948         char            *p;
949
950         *add_rm = *body_lumps = 0;
951         *reply_lump = 0;
952
953         /* calculate the length of the lumps */
954         len = 0;
955         LUMP_LIST_LEN(len, pkg_msg->add_rm);
956         LUMP_LIST_LEN(len, pkg_msg->body_lumps);
957         RPL_LUMP_LIST_LEN(len, pkg_msg->reply_lump);
958
959         if (!len)
960                 return 1; /* nothing to do */
961
962         p=(char *)shm_malloc(len);
963         if (!p)
964         {
965                 LOG(L_ERR, "ERROR: msg_lump_cloner: cannot allocate memory\n" );
966                 return -1;
967         }
968
969         /* clone the lumps */
970         CLONE_LUMP_LIST(add_rm, pkg_msg->add_rm, p);
971         CLONE_LUMP_LIST(body_lumps, pkg_msg->body_lumps, p);
972         CLONE_RPL_LUMP_LIST(reply_lump, pkg_msg->reply_lump, p);
973
974         return 0;
975 }
976
977
978
979 /* vi: set ts=4 sw=4 tw=79:ai:cindent: */