5a25eef5bc7479f078cef0ce40087ec43c49f311
[sip-router] / msg_translator.c
1 /* $Id$
2  *
3  */
4
5
6 #include <sys/socket.h>
7
8 #include "msg_translator.h"
9 #include "mem/mem.h"
10 #include "dprint.h"
11 #include "config.h"
12 #include "md5utils.h"
13 #include <netdb.h>
14
15
16
17 #define MAX_VIA_LINE_SIZE      240
18 #define MAX_RECEIVED_SIZE  57
19
20
21
22
23 /* faster than inet_ntoa */
24 static inline char* q_inet_itoa(unsigned long ip)
25 {
26         static char q_inet_itoa_buf[16]; /* 123.567.901.345\0 */
27         unsigned char* p;
28         unsigned char a,b,c;  /* abc.def.ghi.jkl */
29         int offset;
30         int r;
31         p=(unsigned char*)&ip;
32
33         offset=0;
34         /* unrolled loops (faster)*/
35         for(r=0;r<3;r++){
36                 a=p[r]/100;
37                 c=p[r]%10;
38                 b=p[r]%100/10;
39                 if (a){
40                         q_inet_itoa_buf[offset]=a+'0';
41                         q_inet_itoa_buf[offset+1]=b+'0';
42                         q_inet_itoa_buf[offset+2]=c+'0';
43                         q_inet_itoa_buf[offset+3]='.';
44                         offset+=4;
45                 }else if (b){
46                         q_inet_itoa_buf[offset]=b+'0';
47                         q_inet_itoa_buf[offset+1]=c+'0';
48                         q_inet_itoa_buf[offset+2]='.';
49                         offset+=3;
50                 }else{
51                         q_inet_itoa_buf[offset]=c+'0';
52                         q_inet_itoa_buf[offset+1]='.';
53                         offset+=2;
54                 }
55         }
56         /* last number */
57         a=p[r]/100;
58         c=p[r]%10;
59         b=p[r]%100/10;
60         if (a){
61                 q_inet_itoa_buf[offset]=a+'0';
62                 q_inet_itoa_buf[offset+1]=b+'0';
63                 q_inet_itoa_buf[offset+2]=c+'0';
64                 q_inet_itoa_buf[offset+3]=0;
65         }else if (b){
66
67                 q_inet_itoa_buf[offset+1]=c+'0';
68                 q_inet_itoa_buf[offset+2]=0;
69         }else{
70                 q_inet_itoa_buf[offset]=c+'0';
71                 q_inet_itoa_buf[offset+1]=0;
72         }
73
74         return q_inet_itoa_buf;
75 }
76
77
78
79
80 /* checks if ip is in host(name) and ?host(ip)=name?
81  * ip must be in network byte order!
82  *  resolver = DO_DNS | DO_REV_DNS; if 0 no dns check is made
83  * return 0 if equal */
84 int check_address(unsigned long ip, char *name, int resolver)
85 {
86         struct hostent* he;
87         int i;
88
89         /* maybe we are lucky and name it's an ip */
90         if (strcmp(name, q_inet_itoa( /* *(struct in_addr *)&*/ip ))==0)
91                 return 0;
92         if (resolver&DO_DNS){
93                 DBG("check_address: doing dns lookup\n");
94                 /* try all names ips */
95                 he=gethostbyname(name);
96                 for(i=0;he && he->h_addr_list[i];i++){
97                         if (*(unsigned long*)he->h_addr_list[i]==ip)
98                                 return 0;
99                 }
100         }
101         if (resolver&DO_REV_DNS){
102                 DBG("check_address: doing rev. dns lookup\n");
103                 print_ip(ip);
104                 /* try reverse dns */
105                 he=gethostbyaddr((char*)&ip, sizeof(ip), AF_INET);
106                 if (he && (strcmp(he->h_name, name)==0))
107                         return 0;
108                 for (i=0; he && he->h_aliases[i];i++){
109                         if (strcmp(he->h_aliases[i],name)==0)
110                                 return 0;
111                 }
112         }
113         return -1;
114 }
115
116
117
118
119
120
121
122
123 char* via_builder( struct sip_msg *msg , unsigned int *len )
124 {
125         unsigned int  via_len, branch_len;
126         char               *line_buf;
127
128         line_buf=0;
129
130         line_buf=pkg_malloc(sizeof(char)*MAX_VIA_LINE_SIZE);
131         if (line_buf==0){
132                 LOG(L_ERR, "ERROR: via_builder: out of memory\n");
133                 goto error;
134         }
135         via_len=MY_VIA_LEN+names_len[0]; /* space included in MY_VIA*/
136
137         /* jku: if we compute branches using MD5 it will take 32 bytes */
138         branch_len= (loop_checks ? MY_BRANCH_LEN : MY_BRANCH_LEN -1 + MD5_LEN)+
139                                         msg->add_to_branch_len;
140
141         if ((via_len+port_no_str_len+branch_len+CRLF_LEN)<MAX_VIA_LINE_SIZE){
142                 memcpy(line_buf, MY_VIA, MY_VIA_LEN);
143                 memcpy(line_buf+MY_VIA_LEN, names[0], names_len[0]);
144                 if (port_no!=SIP_PORT){
145                         memcpy(line_buf+via_len, port_no_str, port_no_str_len);
146                         via_len+=port_no_str_len;
147                 }
148
149                 /* jku: branch parameter */
150                 memcpy(line_buf+via_len, MY_BRANCH, MY_BRANCH_LEN );
151                 via_len+=MY_BRANCH_LEN;
152                 /* loop checks ? */
153                 if (loop_checks) {
154
155                         if (check_transaction_quadruple( msg )) {
156                                 str src[5];
157                                 int r;
158
159                                 src[0]= msg->from->body;
160                                 src[1]= msg->to->body;
161                                 src[2]= msg->callid->body;
162                                 src[3]= msg->first_line.u.request.uri;
163                                 src[4]= get_cseq( msg )->number;
164                                 MDStringArray ( line_buf+via_len-1, src, 5 );
165                                 via_len+=MD5_LEN - 1;
166
167                         } else DBG("DEBUG: via_builder: required HFs for "
168                                         "loop checking missing\n");
169                 }
170                 //DBG("DEBUG: XXX will add branch now: %s (%d)\n", msg->add_to_branch_s, msg->add_to_branch_len );
171                 /* someone wants me to add something to branch here ? */
172                 memcpy(line_buf+via_len, msg->add_to_branch_s,
173                                 msg->add_to_branch_len );
174                 via_len+=msg->add_to_branch_len;
175
176                 memcpy(line_buf+via_len, CRLF, CRLF_LEN);
177                 via_len+=CRLF_LEN;
178                 line_buf[via_len]=0; /* null terminate the string*/
179         }else{
180                 LOG(L_ERR, " ERROR: via_builder: via too long (%d)\n",
181                                 via_len);
182                 goto error;
183         }
184
185         *len = via_len;
186         return line_buf;
187
188 error:
189         if (line_buf) pkg_free(line_buf);
190         return 0;
191 }
192
193
194
195
196
197
198
199
200
201
202
203 char * build_req_buf_from_sip_req(      struct sip_msg* msg,
204                                 unsigned int *returned_len)
205 {
206         unsigned int len, new_len, received_len, uri_len, via_len;
207         char* line_buf;
208         char* received_buf;
209         char* tmp;
210         int tmp_len;
211         char* new_buf;
212         char* orig;
213         char* buf;
214         unsigned int offset, s_offset, size;
215         unsigned long source_ip;
216         struct lump *t,*r;
217         struct lump* anchor;
218
219         orig=msg->orig;
220         buf=msg->buf;
221         len=msg->len;
222         source_ip=msg->src_ip;
223         received_len=0;
224         new_buf=0;
225         received_buf=0;
226
227
228         line_buf = via_builder( msg, &via_len );
229         if (!line_buf){
230                 LOG(L_ERR,"ERROR: build_req_buf_from_sip_req: no via received!\n");
231                 goto error1;
232         }
233
234         /* check if received needs to be added */
235         if (check_address(source_ip, msg->via1->host.s, received_dns)!=0){
236                 received_buf=pkg_malloc(sizeof(char)*MAX_RECEIVED_SIZE);
237                 if (received_buf==0){
238                         LOG(L_ERR, "ERROR: build_req_buf_from_sip_req: out of memory\n");
239                         goto error1;
240                 }
241                 /*
242                 received_len=snprintf(received_buf, MAX_RECEIVED_SIZE,
243                                                                 ";received=%s",
244                                                                 inet_ntoa(*(struct in_addr *)&source_ip));
245                 */
246                 memcpy(received_buf, RECEIVED, RECEIVED_LEN);
247                 tmp=q_inet_itoa( /* *(struct in_addr *)& */source_ip);
248                 tmp_len=strlen(tmp);
249                 received_len=RECEIVED_LEN+tmp_len;
250                 memcpy(received_buf+RECEIVED_LEN, tmp, tmp_len);
251                 received_buf[received_len]=0; /*null terminate it */
252         }
253
254         /* add via header to the list */
255         /* try to add it before msg. 1st via */
256         /*add first via, as an anchor for second via*/
257         anchor=anchor_lump(&(msg->add_rm), msg->via1->hdr.s-buf, 0, HDR_VIA);
258         if (anchor==0) goto error;
259         if (insert_new_lump_before(anchor, line_buf, via_len, HDR_VIA)==0)
260                 goto error;
261         /* if received needs to be added, add anchor after host and add it */
262         if (received_len){
263                 if (msg->via1->params.s){
264                                 size= msg->via1->params.s-msg->via1->hdr.s-1; /*compensate
265                                                                                                                           for ';' */
266                 }else{
267                                 size= msg->via1->host.s-msg->via1->hdr.s+msg->via1->host.len;
268                                 if (msg->via1->port!=0){
269                                         size+=strlen(msg->via1->hdr.s+size+1)+1; /* +1 for ':'*/
270                                 }
271                 }
272                 anchor=anchor_lump(&(msg->add_rm),msg->via1->hdr.s-buf+size,0,
273                                 HDR_VIA);
274                 if (anchor==0) goto error;
275                 if (insert_new_lump_after(anchor, received_buf, received_len, HDR_VIA)
276                                 ==0 ) goto error;
277         }
278
279
280         /* compute new msg len and fix overlapping zones*/
281         new_len=len;
282         s_offset=0;
283         for(t=msg->add_rm;t;t=t->next){
284                 for(r=t->before;r;r=r->before){
285                         switch(r->op){
286                                 case LUMP_ADD:
287                                         new_len+=r->len;
288                                         break;
289                                 default:
290                                         /* only ADD allowed for before/after */
291                                         LOG(L_CRIT, "BUG:build_req_buf_from_sip_req: invalid op "
292                                                         "for data lump (%x)\n", r->op);
293                         }
294                 }
295                 switch(t->op){
296                         case LUMP_ADD:
297                                 new_len+=t->len;
298                                 break;
299                         case LUMP_DEL:
300                                 /* fix overlapping deleted zones */
301                                 if (t->u.offset < s_offset){
302                                         /* change len */
303                                         if (t->len>s_offset-t->u.offset)
304                                                         t->len-=s_offset-t->u.offset;
305                                         else t->len=0;
306                                         t->u.offset=s_offset;
307                                 }
308                                 s_offset=t->u.offset+t->len;
309                                 new_len-=t->len;
310                                 break;
311                         case LUMP_NOP:
312                                 /* fix offset if overlapping on a deleted zone */
313                                 if (t->u.offset < s_offset){
314                                         t->u.offset=s_offset;
315                                 }else
316                                         s_offset=t->u.offset;
317                                 /* do nothing */
318                                 break;
319                         debug:
320                                 LOG(L_CRIT,"BUG:build_req_buf_from_sip_req: invalid"
321                                                         " op for data lump (%x)\n", r->op);
322                 }
323                 for (r=t->after;r;r=r->after){
324                         switch(r->op){
325                                 case LUMP_ADD:
326                                         new_len+=r->len;
327                                         break;
328                                 default:
329                                         /* only ADD allowed for before/after */
330                                         LOG(L_CRIT, "BUG:build_req_buf_from_sip_req: invalid"
331                                                                 " op for data lump (%x)\n", r->op);
332                         }
333                 }
334         }
335
336
337         if (msg->new_uri.s){
338                 uri_len=msg->new_uri.len;
339                 new_len=new_len-msg->first_line.u.request.uri.len+uri_len;
340         }
341         new_buf=(char*)malloc(new_len+1);
342         if (new_buf==0){
343                 LOG(L_ERR, "ERROR: build_req_buf_from_sip_req: out of memory\n");
344                 goto error;
345         }
346
347         offset=s_offset=0;
348         if (msg->new_uri.s){
349                 /* copy message up to uri */
350                 size=msg->first_line.u.request.uri.s-buf;
351                 memcpy(new_buf, orig, size);
352                 offset+=size;
353                 s_offset+=size;
354                 /* add our uri */
355                 memcpy(new_buf+offset, msg->new_uri.s, uri_len);
356                 offset+=uri_len;
357                 s_offset+=msg->first_line.u.request.uri.len; /* skip original uri */
358         }
359         new_buf[new_len]=0;
360         /* copy msg adding/removing lumps */
361         for (t=msg->add_rm;t;t=t->next){
362                 switch(t->op){
363                         case LUMP_ADD:
364                                 /* just add it here! */
365                                 /* process before  */
366                                 for(r=t->before;r;r=r->before){
367                                         switch (r->op){
368                                                 case LUMP_ADD:
369                                                         /*just add it here*/
370                                                         memcpy(new_buf+offset, r->u.value, r->len);
371                                                         offset+=r->len;
372                                                         break;
373                                                 default:
374                                                         /* only ADD allowed for before/after */
375                                                         LOG(L_CRIT, "BUG:build_req_buf_from_sip_req: "
376                                                                         "invalid op for data lump (%x)\n", r->op);
377
378                                         }
379                                 }
380                                 /* copy "main" part */
381                                 memcpy(new_buf+offset, t->u.value, t->len);
382                                 offset+=t->len;
383                                 /* process after */
384                                 for(r=t->after;r;r=r->after){
385                                         switch (r->op){
386                                                 case LUMP_ADD:
387                                                         /*just add it here*/
388                                                         memcpy(new_buf+offset, r->u.value, r->len);
389                                                         offset+=r->len;
390                                                         break;
391                                                 default:
392                                                         /* only ADD allowed for before/after */
393                                                         LOG(L_CRIT, "BUG:build_req_buf_from_sip_req: "
394                                                                         "invalid op for data lump (%x)\n", r->op);
395                                         }
396                                 }
397                                 break;
398                         case LUMP_NOP:
399                         case LUMP_DEL:
400                                 /* copy till offset */
401                                 if (s_offset>t->u.offset){
402                                         DBG("Warning: (%d) overlapped lumps offsets,"
403                                                 " ignoring(%x, %x)\n", t->op, s_offset,t->u.offset);
404                                         /* this should've been fixed above (when computing len) */
405                                         /* just ignore it*/
406                                         break;
407                                 }
408                                 size=t->u.offset-s_offset;
409                                 if (size){
410                                         memcpy(new_buf+offset, orig+s_offset,size);
411                                         offset+=size;
412                                         s_offset+=size;
413                                 }
414                                 /* process before  */
415                                 for(r=t->before;r;r=r->before){
416                                         switch (r->op){
417                                                 case LUMP_ADD:
418                                                         /*just add it here*/
419                                                         memcpy(new_buf+offset, r->u.value, r->len);
420                                                         offset+=r->len;
421                                                         break;
422                                                 default:
423                                                         /* only ADD allowed for before/after */
424                                                         LOG(L_CRIT, "BUG:build_req_buf_from_sip_req: "
425                                                                         "invalid op for data lump (%x)\n", r->op);
426
427                                         }
428                                 }
429                                 /* process main (del only) */
430                                 if (t->op==LUMP_DEL){
431                                         /* skip len bytes from orig msg */
432                                         s_offset+=t->len;
433                                 }
434                                 /* process after */
435                                 for(r=t->after;r;r=r->after){
436                                         switch (r->op){
437                                                 case LUMP_ADD:
438                                                         /*just add it here*/
439                                                         memcpy(new_buf+offset, r->u.value, r->len);
440                                                         offset+=r->len;
441                                                         break;
442                                                 default:
443                                                         /* only ADD allowed for before/after */
444                                                         LOG(L_CRIT, "BUG:build_req_buf_from_sip_req: "
445                                                                         "invalid op for data lump (%x)\n", r->op);
446                                         }
447                                 }
448                                 break;
449                         default:
450                                         LOG(L_CRIT, "BUG: build_req_buf_from_sip_req: "
451                                                         "unknown op (%x)\n", t->op);
452                 }
453         }
454         /* copy the rest of the message */
455         memcpy(new_buf+offset, orig+s_offset, len-s_offset);
456         new_buf[new_len]=0;
457
458         *returned_len=new_len;
459         return new_buf;
460
461 error1:
462         if (received_buf) pkg_free(received_buf);
463         if (line_buf) pkg_free(line_buf);
464 error:
465         if (new_buf) free(new_buf);
466         *returned_len=0;
467         return 0;
468 }
469
470
471
472
473 char * build_res_buf_from_sip_res(      struct sip_msg* msg,
474                                                                         unsigned int *returned_len)
475 {
476         unsigned int new_len, via_len,r;
477         char* new_buf;
478         unsigned offset, s_offset, size;
479         struct hostent* he;
480         char* orig;
481         char* buf;
482         unsigned int len;
483 #ifdef DNS_IP_HACK
484         int err;
485 #endif
486
487
488         orig=msg->orig;
489         buf=msg->buf;
490         len=msg->len;
491         new_buf=0;
492         /* we must remove the first via */
493         via_len=msg->via1->bsize;
494         size=msg->via1->hdr.s-buf;
495         DBG("via len: %d, initial size: %d\n", via_len, size);
496         if (msg->via1->next){
497                 /* add hdr size*/
498                 size+=msg->via1->hdr.len+1;
499             DBG(" adjusted via len: %d, initial size: %d\n",
500                                 via_len, size);
501         }else{
502                 /* add hdr size ("Via:")*/
503                 via_len+=msg->via1->hdr.len+1;
504         }
505         new_len=len-via_len;
506
507         DBG(" old size: %d, new size: %d\n", len, new_len);
508         new_buf=(char*)malloc(new_len+1);/* +1 is for debugging
509                                                                                         (\0 to print it )*/
510         if (new_buf==0){
511                 LOG(L_ERR, "ERROR: build_res_buf_from_sip_res: out of memory\n");
512                 goto error;
513         }
514         new_buf[new_len]=0; /* debug: print the message */
515         memcpy(new_buf, orig, size);
516         offset=size;
517         s_offset=size+via_len;
518         memcpy(new_buf+offset,orig+s_offset, len-s_offset);
519          /* send it! */
520         DBG(" copied size: orig:%d, new: %d, rest: %d\n",
521                         s_offset, offset,
522                         len-s_offset );
523
524         *returned_len=new_len;
525         return new_buf;
526 error:
527         if (new_buf) free(new_buf);
528         *returned_len=0;
529         return 0;
530 }
531
532
533
534
535
536 char * build_res_buf_from_sip_req(      unsigned int code ,
537         char *text , struct sip_msg* msg, unsigned int *returned_len)
538 {
539         char                    *buf, *p;
540         unsigned int       len,foo;
541         struct hdr_field  *hdr;
542         int                       i;
543
544         /* force parsing all headers -- we want to return all
545         Via's in the reply and they may be scattered down to the
546         end of header (non-block Vias are a really poor property
547         of SIP :( ) */
548         parse_headers( msg, HDR_EOH );
549
550         /*computes the lenght of the new response buffer*/
551         len = 0;
552         /* first line */
553         len += SIP_VERSION_LEN + 1/*space*/ + 3/*code*/ + 1/*space*/ + strlen(text) + CRLF_LEN/*new line*/;
554         /*headers that will be copied (TO, FROM, CSEQ,CALLID,VIA)*/
555         for ( hdr=msg->headers ; hdr ; hdr=hdr->next )
556                 if ( hdr->type==HDR_VIA || hdr->type==HDR_FROM ||
557                                 hdr->type==HDR_CALLID || hdr->type==HDR_TO ||
558                                 hdr->type==HDR_CSEQ )
559                         len += ((hdr->body.s+hdr->body.len ) - hdr->name.s ) + CRLF_LEN;
560         /* end of message */
561         len += CRLF_LEN; /*new line*/
562
563         /*allocating mem*/
564         buf = 0;
565         buf = (char*) malloc( len+1 );
566         if (!buf)
567         {
568                 LOG(L_ERR, "ERROR: build_res_buf_from_sip_req: out of memory\n");
569                 goto error;
570         }
571
572         /* filling the buffer*/
573         p=buf;
574         /* first line */
575         memcpy( p , SIP_VERSION , SIP_VERSION_LEN );
576         p += SIP_VERSION_LEN;
577         *(p++) = ' ' ;
578         /*code*/
579         for ( i=2 , foo = code  ;  i>=0  ;  i-- , foo=foo/10 )
580                 *(p+i) = '0' + foo - ( foo/10 )*10;
581         p += 3;
582         *(p++) = ' ' ;
583         memcpy( p , text , strlen(text) );
584         p += strlen(text);
585         memcpy( p, CRLF, CRLF_LEN );
586         p+=CRLF_LEN;
587         /* headers*/
588         for ( hdr=msg->headers ; hdr ; hdr=hdr->next )
589                 if ( hdr->type==HDR_VIA || hdr->type==HDR_FROM ||
590                 hdr->type==HDR_CALLID || hdr->type==HDR_TO || hdr->type==HDR_CSEQ )
591                 {
592                         memcpy( p , msg->orig+(hdr->name.s-msg->buf) ,
593                                         ((hdr->body.s+hdr->body.len ) -
594                                         hdr->name.s ) );
595                         p += ((hdr->body.s+hdr->body.len ) - hdr->name.s ) ;
596                         memcpy( p, CRLF, CRLF_LEN );
597                         p+=CRLF_LEN;
598                 }
599
600         memcpy( p, CRLF, CRLF_LEN );
601         p+=CRLF_LEN;
602         *(p++) = 0;
603         *returned_len=len;
604         return buf;
605 error:
606         if (buf) free(buf);
607         *returned_len=0;
608         return 0;
609 }