cd3bb296abe1d7f85eb6762b136c875ebf5138a4
[kamailio] / src / modules / tm / t_fifo.c
1 /*
2  * tm - transaction management module
3  *
4  * Copyright (C) 2001-2003 FhG Fokus
5  *
6  * This file is part of Kamailio, a free SIP server.
7  *
8  * Kamailio is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version
12  *
13  * Kamailio is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  */
23
24
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <fcntl.h>
28 #include <errno.h>
29 #include <string.h>
30 #include <sys/uio.h>
31 #include <unistd.h>
32 #include <fcntl.h>
33 #include <sys/un.h>
34 #include <ctype.h>
35 #include <string.h>
36
37 #include "../../core/str.h"
38 #include "../../core/ut.h"
39 #include "../../core/dprint.h"
40 #include "../../core/mem/mem.h"
41 #include "../../core/usr_avp.h"
42 #include "../../core/parser/parser_f.h"
43 #include "../../core/parser/parse_from.h"
44 #include "../../core/parser/parse_rr.h"
45 #include "../../core/parser/parse_nameaddr.h"
46 #include "../../core/parser/parse_hname2.h"
47 #include "../../core/parser/contact/parse_contact.h"
48 #include "../../core/tsend.h"
49 #include "config.h"
50 #include "t_lookup.h"
51 #include "t_fwd.h"
52 #include "t_funcs.h"
53 #include "t_fifo.h"
54
55
56 /* AF_LOCAL is not defined on solaris */
57 #if !defined(AF_LOCAL)
58 #define AF_LOCAL AF_UNIX
59 #endif
60 #if !defined(PF_LOCAL)
61 #define PF_LOCAL PF_UNIX
62 #endif
63
64
65 /* solaris doesn't have SUN_LEN */
66 #ifndef SUN_LEN
67 #define SUN_LEN(sa)      ( strlen((sa)->sun_path) + \
68                                                 (size_t)(((struct sockaddr_un*)0)->sun_path) )
69 #endif
70
71
72 #define TWRITE_PARAMS          20
73 #define TWRITE_VERSION_S       "0.3"
74 #define TWRITE_VERSION_LEN     (sizeof(TWRITE_VERSION_S)-1)
75
76 #define eol_line_s(_i_)        ( iov_lines_eol[2*(_i_)].iov_base )
77 #define eol_line_len(_i_)      ( iov_lines_eol[2*(_i_)].iov_len )
78
79 #define eol_line(_i_,_s_)      { eol_line_s(_i_) = (_s_).s; \
80                                                                         eol_line_len(_i_) = (_s_).len; }
81
82 #define IDBUF_LEN              128
83 #define ROUTE_BUFFER_MAX       512
84 #define APPEND_BUFFER_MAX      4096
85 #define CMD_BUFFER_MAX         128
86
87 #define copy_route(s,len,rs,rlen) \
88         do {\
89                 if(rlen+len+3 >= ROUTE_BUFFER_MAX){\
90                         LM_ERR("buffer overflow while copying new route\n");\
91                         goto error;\
92                 }\
93                 if(len){\
94                         append_chr(s,','); len++;\
95                 }\
96                 append_chr(s,'<');len++;\
97                 append_str(s,rs,rlen);\
98                 len += rlen; \
99                 append_chr(s,'>');len++;\
100         } while(0)
101
102 static struct iovec iov_lines_eol[2*TWRITE_PARAMS];
103 static struct iovec eol={"\n",1};
104
105 static int sock;
106
107 struct hdr_avp {
108         str title;
109         int type;
110         str sval;
111         int ival;
112         struct hdr_avp *next;
113 };
114
115 struct tw_append {
116         str name;
117         int add_body;
118         struct hdr_avp *elems;
119         struct tw_append *next;
120 };
121
122 struct tw_info {
123         str action;
124         struct tw_append *append;
125 };
126
127 #define ELEM_TYPE_AVP      "avp"
128 #define ELEM_TYPE_AVP_LEN  (sizeof(ELEM_TYPE_AVP)-1)
129 #define ELEM_TYPE_HDR      "hdr"
130 #define ELEM_TYPE_HDR_LEN  (sizeof(ELEM_TYPE_HDR)-1)
131 #define ELEM_TYPE_MSG      "msg"
132 #define ELEM_TYPE_MSG_LEN  (sizeof(ELEM_TYPE_MSG)-1)
133 #define ELEM_IS_AVP        (1<<0)
134 #define ELEM_IS_HDR        (1<<1)
135 #define ELEM_IS_MSG        (1<<2)
136
137 #define ELEM_VAL_BODY      "body"
138 #define ELEM_VAL_BODY_LEN  (sizeof(ELEM_VAL_BODY)-1)
139
140
141 static struct tw_append *tw_appends;
142
143
144 static void print_tw_append( struct tw_append *append)
145 {
146         struct hdr_avp *ha;
147
148         if (!append)
149                 return;
150
151         LM_DBG("tw_append name=<%.*s>\n",
152                 append->name.len,append->name.s);
153         for( ha=append->elems ; ha ; ha=ha->next ) {
154                 LM_DBG("\ttitle=<%.*s>\n",ha->title.len,ha->title.s);
155                 LM_DBG("\t\tttype=<%d>\n",ha->type);
156                 LM_DBG("\t\tsval=<%.*s>\n",ha->sval.len,ha->sval.s);
157                 LM_DBG("\t\tival=<%d>\n",ha->ival);
158         }
159 }
160
161
162 /* tw_append syntax:
163  * tw_append = name:element[;element]
164  * element   = [title=]value
165  * value     = avp[avp_spec] | hdr[hdr_name] | msg[body] */
166 int parse_tw_append( modparam_t type, void* val)
167 {
168         struct hdr_field hdr;
169         struct hdr_avp *last;
170         struct hdr_avp *ha=NULL;
171         struct tw_append *app;
172         int_str avp_name;
173         char *s;
174         char bar;
175         str foo;
176         int n;
177         int index;
178
179         if (val==0 || ((char*)val)[0]==0)
180                 return 0;
181         s = (char*)val;
182
183         /* start parsing - first the name */
184         while( *s && isspace((int)*s) )  s++;
185         if ( !*s || *s==':')
186                 goto parse_error;
187         foo.s = s;
188         while ( *s && *s!=':' && !isspace((int)*s) ) s++;
189         if ( !*s || foo.s==s )
190                 goto parse_error;
191         foo.len = s - foo.s;
192         /* parse separator */
193         while( *s && isspace((int)*s) )  s++;
194         if ( !*s || *s!=':')
195                 goto parse_error;
196         s++;
197         while( *s && isspace((int)*s) )  s++;
198         if ( !*s )
199                 goto parse_error;
200
201         /* check for name duplication */
202         for(app=tw_appends;app;app=app->next)
203                 if (app->name.len==foo.len && !strncasecmp(app->name.s,foo.s,foo.len)){
204                         LM_ERR("duplicated tw_append name <%.*s>\n",foo.len,foo.s);
205                         goto error;
206                 }
207
208         /* new tw_append structure */
209         app = (struct tw_append*)pkg_malloc( sizeof(struct tw_append) );
210         if (app==0) {
211                 PKG_MEM_ERROR;
212                 goto error;
213         }
214         app->name.s = (char*)pkg_malloc( foo.len+1 );
215         if (app->name.s==0) {
216                 PKG_MEM_ERROR;
217                 goto error;
218         }
219         memcpy( app->name.s, foo.s, foo.len);
220         app->name.len = foo.len;
221         app->name.s[app->name.len] = 0;
222         last = app->elems = 0;
223         app->next = tw_appends;
224         tw_appends = app;
225
226         /* parse the elements */
227         while (*s) {
228                 /* parse element title or element type */
229                 foo.s = s;
230                 while( *s && *s!='[' && *s!='=' && *s!=';' && !isspace((int)*s) ) s++;
231                 if ( !*s || foo.s==s)
232                         goto parse_error;
233                 foo.len = s - foo.s;
234                 /* new hdr_avp structure */
235                 ha = (struct hdr_avp*)pkg_malloc( sizeof(struct hdr_avp) );
236                 if (ha==0) {
237                         PKG_MEM_ERROR;
238                         goto error;
239                 }
240                 memset( ha, 0, sizeof(struct hdr_avp));
241                 if (*s!='[') {
242                         /* foo must by title or some error -> parse separator */
243                         while( *s && isspace((int)*s) )  s++;
244                         if ( !*s || *s!='=')
245                                 goto parse_error;
246                         s++;
247                         while( *s && isspace((int)*s) )  s++;
248                         if ( !*s )
249                                 goto parse_error;
250                         /* set the title */
251                         ha->title.s = (char*)pkg_malloc( foo.len+1 );
252                         if (ha->title.s==0) {
253                                 PKG_MEM_ERROR;
254                                 goto error;
255                         }
256                         memcpy( ha->title.s, foo.s, foo.len);
257                         ha->title.len = foo.len;
258                         ha->title.s[ha->title.len] = 0;
259                         /* parse the type now */
260                         foo.s = s;
261                         while( *s && *s!='[' && *s!=']' && *s!=';' && !isspace((int)*s) )
262                                 s++;
263                         if ( *s!='[' || foo.s==s)
264                                 goto parse_error;
265                         foo.len = s - foo.s;
266                 }
267                 /* foo containes the elemet type */
268                 if ( foo.len==ELEM_TYPE_AVP_LEN &&
269                 !strncasecmp( foo.s, ELEM_TYPE_AVP, foo.len) ) {
270                         ha->type = ELEM_IS_AVP;
271                 } else if ( foo.len==ELEM_TYPE_HDR_LEN &&
272                 !strncasecmp( foo.s, ELEM_TYPE_HDR, foo.len) ) {
273                         ha->type = ELEM_IS_HDR;
274                 } else if ( foo.len==ELEM_TYPE_MSG_LEN &&
275                 !strncasecmp( foo.s, ELEM_TYPE_MSG, foo.len) ) {
276                         ha->type = ELEM_IS_MSG;
277                 } else {
278                         LM_ERR("unknown type <%.*s>\n", foo.len, foo.s);
279                         goto error;
280                 }
281                 /* parse the element name */
282                 s++;
283                 foo.s = s;
284                 while( *s && *s!=']' && *s!=';' && !isspace((int)*s) ) s++;
285                 if ( *s!=']' || foo.s==s )
286                         goto parse_error;
287                 foo.len = s - foo.s;
288                 s++;
289                 /* process and optimize the element name */
290                 if (ha->type==ELEM_IS_AVP) {
291                         /* element is AVP */
292                         if ( parse_avp_spec( &foo, &n, &avp_name, &index)!=0 ) {
293                                 LM_ERR("bad alias spec <%.*s>\n",foo.len, foo.s);
294                                 goto error;
295                         }
296                         if (n&AVP_NAME_STR) {
297                                 /* string name */
298                                 ha->sval.s = (char*)pkg_malloc(avp_name.s.len+1);
299                                 if (ha->sval.s==0) {
300                                         PKG_MEM_ERROR;
301                                         goto error;
302                                 }
303                                 memcpy( ha->sval.s, avp_name.s.s, avp_name.s.len);
304                                 ha->sval.len = avp_name.s.len;
305                                 ha->sval.s[ha->sval.len] = 0;
306                                 if (ha->title.s==0)
307                                         ha->title = ha->sval;
308                         } else {
309                                 /* ID name - if title is missing, convert the ID to
310                                  * string and us it a title */
311                                 ha->ival = avp_name.n;
312                                 if (ha->title.s==0) {
313                                         foo.s=int2str((unsigned long)ha->ival, &foo.len);
314                                         ha->title.s = (char*)pkg_malloc( n+1 );
315                                         if (ha->title.s==0) {
316                                                 PKG_MEM_ERROR;
317                                                 goto error;
318                                         }
319                                         memcpy( ha->title.s, foo.s, foo.len);
320                                         ha->title.len = foo.len;
321                                         ha->title.s[ha->title.len] = 0;
322                                 }
323                         }
324                 } else if (ha->type==ELEM_IS_HDR) {
325                         /* element is HDR -  try to get it's coded type if defined */
326                         bar = foo.s[foo.len];
327                         foo.s[foo.len] = ':';
328                         /* parse header name */
329                         if (parse_hname2( foo.s, foo.s+foo.len+1, &hdr)==0) {
330                                 LM_ERR("BUG: parse header failed\n");
331                                 goto error;
332                         }
333                         foo.s[foo.len] = bar;
334                         ha->ival = hdr.type;
335                         if (hdr.type==HDR_OTHER_T || ha->title.s==0) {
336                                 /* duplicate hdr name */
337                                 ha->sval.s = (char*)pkg_malloc(foo.len+1);
338                                 if (ha->sval.s==0) {
339                                         PKG_MEM_ERROR;
340                                         goto error;
341                                 }
342                                 memcpy( ha->sval.s, foo.s, foo.len);
343                                 ha->sval.len = foo.len;
344                                 ha->sval.s[ha->sval.len] = 0;
345                                 if (ha->title.s==0)
346                                         ha->title = ha->sval;
347                         }
348                 } else {
349                         /* element is MSG */
350                         if ( !(foo.len==ELEM_VAL_BODY_LEN &&
351                         !strncasecmp(ELEM_VAL_BODY,foo.s,foo.len)) ) {
352                                 LM_ERR("unsupported value <%.*s> for msg type\n",foo.len,foo.s);
353                                 goto error;
354                         }
355                         app->add_body = 1;
356                         pkg_free( ha );
357                         ha = 0;
358                 }
359
360                 /* parse the element separator, if present */
361                 while( *s && isspace((int)*s) )  s++;
362                 if ( *s && *s!=';')
363                         goto parse_error;
364                 if (*s==';') {
365                         s++;
366                         while( *s && isspace((int)*s) )  s++;
367                         if (!*s)
368                                 goto parse_error;
369                 }
370
371                 /* link the element to tw_append structure */
372                 if (ha) {
373                         if (last==0) {
374                                 last = app->elems = ha;
375                         } else {
376                                 last->next = ha;
377                                 last = ha;
378                         }
379                         ha = NULL;
380                 }
381
382         } /* end while */
383
384         print_tw_append( app );
385         /* free the old string */
386         pkg_free(val);
387         return 0;
388 parse_error:
389         LM_ERR("parse error in <%s> around position %ld\n",
390                         (char*)val, (long)(s-(char*)val));
391 error:
392         if(ha) pkg_free(ha);
393         return -1;
394 }
395
396
397 static struct tw_append *search_tw_append(char *name, int len)
398 {
399         struct tw_append * app;
400
401         for( app=tw_appends ; app ; app=app->next )
402                 if (app->name.len==len && !strncasecmp(app->name.s,name,len) )
403                         return app;
404         return 0;
405 }
406
407
408 int fixup_t_write( void** param, int param_no)
409 {
410         struct tw_info *twi;
411         char *s;
412
413         if (param_no==2) {
414                 twi = (struct tw_info*)pkg_malloc( sizeof(struct tw_info) );
415                 if (twi==0) {
416                         PKG_MEM_ERROR;
417                         return E_OUT_OF_MEM;
418                 }
419                 memset( twi, 0 , sizeof(struct tw_info));
420                 s = (char*)*param;
421                 twi->action.s = s;
422                 if ( (s=strchr(s,'/'))!=0) {
423                         twi->action.len = s - twi->action.s;
424                         if (twi->action.len==0) {
425                                 LM_ERR("empty action name\n");
426                                 pkg_free(twi);
427                                 return E_CFG;
428                         }
429                         s++;
430                         if (*s==0) {
431                                 LM_ERR("empty append name\n");
432                                 pkg_free(twi);
433                                 return E_CFG;
434                         }
435                         twi->append = search_tw_append( s, strlen(s));
436                         if (twi->append==0) {
437                                 LM_ERR("unknown append name <%s>\n",s);
438                                 pkg_free(twi);
439                                 return E_CFG;
440                         }
441                 } else {
442                         twi->action.len = strlen(twi->action.s);
443                 }
444                 *param=(void*)twi;
445         }
446
447         return 0;
448 }
449
450
451 int init_twrite_sock(void)
452 {
453         int flags;
454
455         sock = socket(PF_LOCAL, SOCK_DGRAM, 0);
456         if (sock == -1) {
457                 LM_ERR("unable to create socket: %s\n", strerror(errno));
458                 return -1;
459         }
460
461         /* Turn non-blocking mode on */
462         flags = fcntl(sock, F_GETFL);
463         if (flags == -1){
464                 LM_ERR("fcntl failed: %s\n", strerror(errno));
465                 close(sock);
466                 return -1;
467         }
468
469         if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1) {
470                 LM_ERR("fcntl: set non-blocking failed: %s\n", strerror(errno));
471                 close(sock);
472                 return -1;
473         }
474         return 0;
475 }
476
477
478 int init_twrite_lines()
479 {
480         int i;
481
482         /* init the line table */
483         for(i=0;i<TWRITE_PARAMS;i++) {
484                 iov_lines_eol[2*i].iov_base = 0;
485                 iov_lines_eol[2*i].iov_len = 0;
486                 iov_lines_eol[2*i+1] = eol;
487         }
488
489         /* first line is the version - fill it now */
490         eol_line_s(0)   = TWRITE_VERSION_S;
491         eol_line_len(0) = TWRITE_VERSION_LEN;
492
493         return 0;
494 }
495
496
497 static int inline write_to_fifo(char *fifo, int cnt )
498 {
499         int   fd_fifo;
500
501         /* open FIFO file stream */
502         if((fd_fifo = open(fifo,O_WRONLY | O_NONBLOCK)) == -1){
503                 switch(errno){
504                         case ENXIO:
505                                 LM_ERR("cannot open fifo file - nobody listening for reading"
506                                         " [%s] (%s)\n", fifo, strerror(errno));
507                                 break;
508                         default:
509                                 LM_ERR("failed to open [%s] fifo: %s\n", fifo, strerror(errno));
510                 }
511                 goto error;
512         }
513
514         /* write now (unbuffered straight-down write) */
515 repeat:
516         if (writev(fd_fifo, iov_lines_eol, 2*cnt)<0) {
517                 if (errno!=EINTR) {
518                         LM_ERR("writev failed: %s\n", strerror(errno));
519                         close(fd_fifo);
520                         goto error;
521                 } else {
522                         goto repeat;
523                 }
524         }
525         close(fd_fifo);
526
527         LM_DBG("write completed\n");
528         return 1; /* OK */
529
530 error:
531         return -1;
532 }
533
534
535 static inline char* add2buf(char *buf, char *end, char *title, int title_len,
536                         char *value , int value_len)
537 {
538         if (buf+title_len+value_len+2+1>=end)
539                 return 0;
540         memcpy( buf, title, title_len);
541         buf += title_len;
542         *(buf++) = ':';
543         *(buf++) = ' ';
544         memcpy( buf, value, value_len);
545         buf += value_len;
546         *(buf++) = '\n';
547         return buf;
548 }
549
550
551 static inline char* append2buf( char *buf, int len, struct sip_msg *req,
552                         struct hdr_avp *ha)
553 {
554         struct hdr_field *hdr;
555         struct usr_avp   *avp;
556         int_str          avp_val;
557         int_str          avp_name;
558         char  *end;
559         str   foo;
560         int   msg_parsed;
561
562         end = buf+len;
563         msg_parsed = 0;
564
565         while(ha) {
566                 if (ha->type==ELEM_IS_AVP) {
567                         /* search for the AVP */
568                         if (ha->sval.s) {
569                                 avp_name.s=ha->sval;
570                                 avp = search_first_avp( AVP_NAME_STR, avp_name, &avp_val, 0);
571                                 LM_DBG("AVP <%.*s>: %p\n",avp_name.s.len, avp_name.s.s, avp);
572                         } else {
573                                 avp_name.n=ha->ival;
574                                 avp = search_first_avp( 0, avp_name, &avp_val, 0);
575                                 LM_DBG("AVP <%i>: %p\n",avp_name.n,avp);
576                         }
577                         if (avp) {
578                                 if (avp->flags&AVP_VAL_STR) {
579                                         buf=add2buf( buf, end, ha->title.s, ha->title.len,
580                                                 avp_val.s.s , avp_val.s.len);
581                                         if (!buf)
582                                                 goto overflow_err;
583                                 } else {
584                                         foo.s=int2str( (unsigned long)avp_val.n, &foo.len);
585                                         buf=add2buf( buf, end, ha->title.s, ha->title.len,
586                                                 foo.s , foo.len);
587                                         if (!buf)
588                                                 goto overflow_err;
589                                 }
590                         }
591                 } else if (ha->type==ELEM_IS_HDR) {
592                         /* parse the HDRs */
593                         if (!msg_parsed) {
594                                 if (parse_headers( req, HDR_EOH_F, 0)!=0) {
595                                         LM_ERR("parsing hdrs failed\n");
596                                         goto error;
597                                 }
598                                 msg_parsed = 1;
599                         }
600                         /* search the HDR */
601                         if (ha->ival==HDR_OTHER_T) {
602                                 for(hdr=req->headers;hdr;hdr=hdr->next)
603                                         if (ha->sval.len==hdr->name.len &&
604                                         strncasecmp( ha->sval.s, hdr->name.s, hdr->name.len)==0)
605                                                 break;
606                         } else {
607                                 for(hdr=req->headers;hdr;hdr=hdr->next)
608                                         if (ha->ival==hdr->type)
609                                                 break;
610                         }
611                         if (hdr) {
612                                 trim_len( foo.len, foo.s, hdr->body);
613                                 buf=add2buf( buf, end, ha->title.s, ha->title.len,
614                                         foo.s , foo.len);
615                                 if (!buf)
616                                         goto overflow_err;
617                         }
618                 } else {
619                         LM_ERR("BUG: unknown element type %d\n", ha->type);
620                         goto error;
621                 }
622
623                 ha = ha->next;
624         }
625
626         return buf;
627 overflow_err:
628         LM_ERR("overflow -> append exceeded %d len\n",len);
629 error:
630         return 0;
631 }
632
633
634 static int assemble_msg(struct sip_msg* msg, struct tw_info *twi)
635 {
636         static char     id_buf[IDBUF_LEN];
637         static char     route_buffer[ROUTE_BUFFER_MAX];
638         static char     append_buf[APPEND_BUFFER_MAX];
639         static char     cmd_buf[CMD_BUFFER_MAX];
640         static str      empty_param = STR_STATIC_INIT(".");
641         unsigned int      hash_index, label;
642         contact_body_t*   cb=0;
643         contact_t*        c=0;
644         name_addr_t       na;
645         rr_t*             record_route;
646         struct hdr_field* p_hdr;
647         param_hooks_t     hooks;
648         int               l;
649         char*             s, fproxy_lr;
650         int               first_rr;
651         str               route, next_hop, append, tmp_s, body, str_uri;
652
653         if(msg->first_line.type != SIP_REQUEST){
654                 LM_ERR("called for something else thena SIP request\n");
655                 goto error;
656         }
657
658         /* parse all -- we will need every header field for a UAS */
659         if ( parse_headers(msg, HDR_EOH_F, 0)==-1) {
660                 LM_ERR("parse_headers failed\n");
661                 goto error;
662         }
663
664         /* find index and hash; (the transaction can be safely used due
665          * to refcounting till script completes) */
666         if( t_get_trans_ident(msg,&hash_index,&label) == -1 ) {
667                 LM_ERR("assemble_msg: t_get_trans_ident failed\n");
668                 goto error;
669         }
670
671         /* parse from header */
672         if (msg->from==0 || (msg->from->parsed==0 && parse_from_header(msg)==-1)) {
673                 LM_ERR("while parsing <From:> header\n");
674                 goto error;
675         }
676
677         /* parse the RURI (doesn't make any malloc) */
678         msg->parsed_uri_ok = 0; /* force parsing */
679         if (parse_sip_msg_uri(msg)<0) {
680                 LM_ERR("uri has not been parsed\n");
681                 goto error;
682         }
683
684         /* parse contact header */
685         str_uri.s = 0;
686         str_uri.len = 0;
687         if(msg->contact) {
688                 if (msg->contact->parsed==0 && parse_contact(msg->contact)==-1) {
689                         LM_ERR("error while parsing 'Contact' header\n");
690                         goto error;
691                 }
692                 cb = (contact_body_t*)msg->contact->parsed;
693                 if(cb && (c=cb->contacts)) {
694                         str_uri = c->uri;
695                         if (find_not_quoted(&str_uri,'<')) {
696                                 parse_nameaddr(&str_uri,&na);
697                                 str_uri = na.uri;
698                         }
699                 }
700         }
701
702         /* str_uri is taken from caller's contact or from header
703          * for backwards compatibility with pre-3261 (from is already parsed)*/
704         if(!str_uri.len || !str_uri.s)
705                 str_uri = get_from(msg)->uri;
706
707         /* parse Record-Route headers */
708         route.s = s = route_buffer; route.len = 0;
709         fproxy_lr = 0;
710         next_hop = empty_param;
711
712         p_hdr = msg->record_route;
713         if(p_hdr) {
714                 if (p_hdr->parsed==0 && parse_rr(p_hdr)!=0 ) {
715                         LM_ERR("while parsing 'Record-Route' header\n");
716                         goto error;
717                 }
718                 record_route = (rr_t*)p_hdr->parsed;
719         } else {
720                 record_route = 0;
721         }
722
723         first_rr = 1;
724
725         if( record_route ) {
726                 if ( (tmp_s.s=find_not_quoted(&record_route->nameaddr.uri,';'))!=0 &&
727                 tmp_s.s+1!=record_route->nameaddr.uri.s+
728                 record_route->nameaddr.uri.len) {
729                         /* Parse all parameters */
730                         tmp_s.len = record_route->nameaddr.uri.len - (tmp_s.s-
731                                 record_route->nameaddr.uri.s);
732                         if (parse_params( &tmp_s, CLASS_URI, &hooks,
733                         &record_route->params) < 0) {
734                                 LM_ERR("error while parsing record route uri params\n");
735                                 goto error;
736                         }
737                         fproxy_lr = (hooks.uri.lr != 0);
738                         LM_DBG("record_route->nameaddr.uri: %.*s\n",
739                                 record_route->nameaddr.uri.len,record_route->nameaddr.uri.s);
740                         if(fproxy_lr){
741                                 first_rr = 0;
742                                 LM_DBG("first proxy has loose routing.\n");
743                                 copy_route(s,route.len,record_route->nameaddr.uri.s,
744                                         record_route->nameaddr.uri.len);
745                         }
746                 }
747                 for(;p_hdr;p_hdr = p_hdr->next) {
748                         /* filter out non-RR hdr and empty hdrs */
749                         if( (p_hdr->type!=HDR_RECORDROUTE_T) || p_hdr->body.len==0)
750                                 continue;
751
752                         if(p_hdr->parsed==0 && parse_rr(p_hdr)!=0 ){
753                                 LM_ERR("while parsing 'Record-route' header\n");
754                                 goto error;
755                         }
756                         for(record_route=p_hdr->parsed; record_route;
757                                                 record_route=record_route->next){
758                                 LM_DBG("record_route->nameaddr.uri: <%.*s>\n",
759                                                 record_route->nameaddr.uri.len,
760                                                 record_route->nameaddr.uri.s);
761                                 if (!first_rr) {
762                                         copy_route(s,route.len,record_route->nameaddr.uri.s,
763                                                         record_route->nameaddr.uri.len);
764                                 }
765                                 first_rr=0;
766                         }
767                 }
768
769                 if(!fproxy_lr){
770                         copy_route(s,route.len,str_uri.s,str_uri.len);
771                         str_uri = ((rr_t*)msg->record_route->parsed)->nameaddr.uri;
772                 } else {
773                         next_hop = ((rr_t*)msg->record_route->parsed)->nameaddr.uri;
774                 }
775         }
776
777         LM_DBG("calculated route: %.*s\n", route.len,route.len ? route.s : "");
778         LM_DBG("next r-uri: %.*s\n", str_uri.len,str_uri.len ? str_uri.s : "");
779
780         if ( REQ_LINE(msg).method_value==METHOD_INVITE ||
781                         REQ_LINE(msg).method_value==METHOD_INFO ||
782                         (twi->append && twi->append->add_body) ) {
783                 /* get body */
784                 if( (body.s = get_body(msg)) == 0 ){
785                         LM_ERR("get_body failed\n");
786                         goto error;
787                 }
788                 body.len = msg->len - (body.s - msg->buf);
789         } else {
790                 body = empty_param;
791         }
792
793         /* additional headers */
794         append.s = s = append_buf;
795         if (sizeof(flag_t)*2+12+1 >= APPEND_BUFFER_MAX) {
796                 LM_ERR("buffer overflow while copying optional header\n");
797                 goto error;
798         }
799         append_str(s,"P-MsgFlags: ",12);
800         l = APPEND_BUFFER_MAX - (12+1); /* include trailing `\n'*/
801
802         if (int2reverse_hex(&s, &l, (int)msg->msg_flags) == -1) {
803                 LM_ERR("buffer overflow while copying optional header\n");
804                 goto error;
805         }
806         append_chr(s,'\n');
807
808         if ( twi->append && ((s=append2buf( s, APPEND_BUFFER_MAX-(s-append.s), msg,
809         twi->append->elems))==0) )
810                 goto error;
811
812         /* body separator */
813         append_chr(s,'.');
814         append.len = s-append.s;
815
816         eol_line_s(1) = s = cmd_buf;
817         if(twi->action.len+12 >= CMD_BUFFER_MAX){
818                 LM_ERR("buffer overflow while copying command name\n");
819                 goto error;
820         }
821         append_str(s,"sip_request.",12);
822         append_str(s,twi->action.s, twi->action.len);
823         eol_line_len(1) = s - (char*)eol_line_s(1);
824
825         eol_line(2,REQ_LINE(msg).method);     /* method type */
826         eol_line(3,msg->parsed_uri.user);     /* user from r-uri */
827         eol_line(4,msg->parsed_uri.host);     /* domain */
828
829         eol_line(5,msg->rcv.bind_address->address_str); /* dst ip */
830
831         eol_line(6,msg->rcv.dst_port==SIP_PORT ?
832                         empty_param : msg->rcv.bind_address->port_no_str); /* port */
833
834         /* r_uri ('Contact:' for next requests) */
835         eol_line(7,msg->first_line.u.request.uri);
836
837         /* r_uri for subsequent requests */
838         eol_line(8,str_uri.len?str_uri:empty_param);
839
840         eol_line(9,get_from(msg)->body);                /* from */
841         eol_line(10,msg->to->body);                     /* to */
842         eol_line(11,msg->callid->body);         /* callid */
843         eol_line(12,get_from(msg)->tag_value);  /* from tag */
844         eol_line(13,get_to(msg)->tag_value);    /* to tag */
845         eol_line(14,get_cseq(msg)->number);     /* cseq number */
846
847         eol_line_s(15)=id_buf;       /* hash:label */
848         s = int2str(hash_index, &l);
849         if (l+1>=IDBUF_LEN) {
850                 LM_ERR("too big hash\n");
851                 goto error;
852         }
853         memcpy(id_buf, s, l);
854         id_buf[l]=':';
855         eol_line_len(15)=l+1;
856         s = int2str(label, &l);
857         if (l+1+eol_line_len(15)>=IDBUF_LEN) {
858                 LM_ERR("too big label\n");
859                 goto error;
860         }
861         memcpy(id_buf+eol_line_len(15), s, l);
862         eol_line_len(15) += l;
863
864         eol_line(16, route.len ? route : empty_param );
865         eol_line(17, next_hop );
866         eol_line(18, append );
867         eol_line(19, body );
868
869         /* success */
870         return 1;
871 error:
872         /* 0 would lead to immediate script exit -- -1 returns
873          * with 'false' to script processing */
874         return -1;
875 }
876
877
878 static int write_to_unixsock(char* sockname, int cnt)
879 {
880         int len, e;
881         struct sockaddr_un dest;
882
883         if (!sockname) {
884                 LM_ERR("Invalid parameter\n");
885                 return E_UNSPEC;
886         }
887
888         len = strlen(sockname);
889         if (len == 0) {
890                 LM_DBG("Error - empty socket name\n");
891                 return -1;
892         } else if (len > 107) {
893                 LM_ERR("Socket name too long\n");
894                 return -1;
895         }
896
897         memset(&dest, 0, sizeof(dest));
898         dest.sun_family = PF_LOCAL;
899         memcpy(dest.sun_path, sockname, len);
900 #ifdef HAVE_SOCKADDR_SA_LEN
901         dest.sun_len = len;
902 #endif
903
904         e = connect(sock, (struct sockaddr*)&dest, SUN_LEN(&dest));
905 #ifdef HAVE_CONNECT_ECONNRESET_BUG
906         /*
907          * Workaround for a nasty bug in BSD kernels dated back
908          * to the Berkeley days, so that can be found in many modern
909          * BSD-derived kernels. Workaround should be pretty harmless since
910          * in normal conditions connect(2) can never return ECONNRESET.
911          */
912         if ((e == -1) && (errno == ECONNRESET))
913                 e = 0;
914 #endif
915         if (e == -1) {
916                 LM_ERR("error in connect: %s\n", strerror(errno));
917                 return -1;
918         }
919
920         if (tsend_dgram_ev(sock, iov_lines_eol, 2 * cnt,
921                         cfg_get(tm, tm_cfg, tm_unix_tx_timeout)) < 0) {
922                 LM_ERR("writev failed: %s\n", strerror(errno));
923                 return -1;
924         }
925
926         return 0;
927 }
928
929
930 int t_write_req(struct sip_msg* msg, char* vm_fifo, char* info)
931 {
932         if (assemble_msg(msg, (struct tw_info*)info) < 0) {
933                 LM_ERR("error int assemble_msg\n");
934                 return -1;
935         }
936
937         if (write_to_fifo(vm_fifo, TWRITE_PARAMS) == -1) {
938                 LM_ERR("write_to_fifo failed\n");
939                 return -1;
940         }
941
942         /* make sure that if voicemail does not initiate a reply
943          * timely, a SIP timeout will be sent out */
944         if (add_blind_uac() == -1) {
945                 LM_ERR("add_blind failed\n");
946                 return -1;
947         }
948         return 1;
949 }
950
951
952 int t_write_unix(struct sip_msg* msg, char* socket, char* info)
953 {
954         if (assemble_msg(msg, (struct tw_info*)info) < 0) {
955                 LM_ERR("error in assemble_msg\n");
956                 return -1;
957         }
958
959         if (write_to_unixsock(socket, TWRITE_PARAMS) == -1) {
960                 LM_ERR("write_to_unixsock failed\n");
961                 return -1;
962         }
963
964         /* make sure that if voicemail does not initiate a reply
965          * timely, a SIP timeout will be sent out */
966         if (add_blind_uac() == -1) {
967                 LM_ERR("add_blind failed\n");
968                 return -1;
969         }
970         return 1;
971 }