tm: t_fifo.c - free app in case of error
[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                 pkg_free(app);
218                 goto error;
219         }
220         memcpy( app->name.s, foo.s, foo.len);
221         app->name.len = foo.len;
222         app->name.s[app->name.len] = 0;
223         last = app->elems = 0;
224         app->next = tw_appends;
225         tw_appends = app;
226
227         /* parse the elements */
228         while (*s) {
229                 /* parse element title or element type */
230                 foo.s = s;
231                 while( *s && *s!='[' && *s!='=' && *s!=';' && !isspace((int)*s) ) s++;
232                 if ( !*s || foo.s==s)
233                         goto parse_error;
234                 foo.len = s - foo.s;
235                 /* new hdr_avp structure */
236                 ha = (struct hdr_avp*)pkg_malloc( sizeof(struct hdr_avp) );
237                 if (ha==0) {
238                         PKG_MEM_ERROR;
239                         goto error;
240                 }
241                 memset( ha, 0, sizeof(struct hdr_avp));
242                 if (*s!='[') {
243                         /* foo must by title or some error -> parse separator */
244                         while( *s && isspace((int)*s) )  s++;
245                         if ( !*s || *s!='=')
246                                 goto parse_error;
247                         s++;
248                         while( *s && isspace((int)*s) )  s++;
249                         if ( !*s )
250                                 goto parse_error;
251                         /* set the title */
252                         ha->title.s = (char*)pkg_malloc( foo.len+1 );
253                         if (ha->title.s==0) {
254                                 PKG_MEM_ERROR;
255                                 goto error;
256                         }
257                         memcpy( ha->title.s, foo.s, foo.len);
258                         ha->title.len = foo.len;
259                         ha->title.s[ha->title.len] = 0;
260                         /* parse the type now */
261                         foo.s = s;
262                         while( *s && *s!='[' && *s!=']' && *s!=';' && !isspace((int)*s) )
263                                 s++;
264                         if ( *s!='[' || foo.s==s)
265                                 goto parse_error;
266                         foo.len = s - foo.s;
267                 }
268                 /* foo containes the elemet type */
269                 if ( foo.len==ELEM_TYPE_AVP_LEN &&
270                 !strncasecmp( foo.s, ELEM_TYPE_AVP, foo.len) ) {
271                         ha->type = ELEM_IS_AVP;
272                 } else if ( foo.len==ELEM_TYPE_HDR_LEN &&
273                 !strncasecmp( foo.s, ELEM_TYPE_HDR, foo.len) ) {
274                         ha->type = ELEM_IS_HDR;
275                 } else if ( foo.len==ELEM_TYPE_MSG_LEN &&
276                 !strncasecmp( foo.s, ELEM_TYPE_MSG, foo.len) ) {
277                         ha->type = ELEM_IS_MSG;
278                 } else {
279                         LM_ERR("unknown type <%.*s>\n", foo.len, foo.s);
280                         goto error;
281                 }
282                 /* parse the element name */
283                 s++;
284                 foo.s = s;
285                 while( *s && *s!=']' && *s!=';' && !isspace((int)*s) ) s++;
286                 if ( *s!=']' || foo.s==s )
287                         goto parse_error;
288                 foo.len = s - foo.s;
289                 s++;
290                 /* process and optimize the element name */
291                 if (ha->type==ELEM_IS_AVP) {
292                         /* element is AVP */
293                         if ( parse_avp_spec( &foo, &n, &avp_name, &index)!=0 ) {
294                                 LM_ERR("bad alias spec <%.*s>\n",foo.len, foo.s);
295                                 goto error;
296                         }
297                         if (n&AVP_NAME_STR) {
298                                 /* string name */
299                                 ha->sval.s = (char*)pkg_malloc(avp_name.s.len+1);
300                                 if (ha->sval.s==0) {
301                                         PKG_MEM_ERROR;
302                                         goto error;
303                                 }
304                                 memcpy( ha->sval.s, avp_name.s.s, avp_name.s.len);
305                                 ha->sval.len = avp_name.s.len;
306                                 ha->sval.s[ha->sval.len] = 0;
307                                 if (ha->title.s==0)
308                                         ha->title = ha->sval;
309                         } else {
310                                 /* ID name - if title is missing, convert the ID to
311                                  * string and us it a title */
312                                 ha->ival = avp_name.n;
313                                 if (ha->title.s==0) {
314                                         foo.s=int2str((unsigned long)ha->ival, &foo.len);
315                                         ha->title.s = (char*)pkg_malloc( n+1 );
316                                         if (ha->title.s==0) {
317                                                 PKG_MEM_ERROR;
318                                                 goto error;
319                                         }
320                                         memcpy( ha->title.s, foo.s, foo.len);
321                                         ha->title.len = foo.len;
322                                         ha->title.s[ha->title.len] = 0;
323                                 }
324                         }
325                 } else if (ha->type==ELEM_IS_HDR) {
326                         /* element is HDR -  try to get it's coded type if defined */
327                         bar = foo.s[foo.len];
328                         foo.s[foo.len] = ':';
329                         /* parse header name */
330                         if (parse_hname2( foo.s, foo.s+foo.len+1, &hdr)==0) {
331                                 LM_ERR("BUG: parse header failed\n");
332                                 goto error;
333                         }
334                         foo.s[foo.len] = bar;
335                         ha->ival = hdr.type;
336                         if (hdr.type==HDR_OTHER_T || ha->title.s==0) {
337                                 /* duplicate hdr name */
338                                 ha->sval.s = (char*)pkg_malloc(foo.len+1);
339                                 if (ha->sval.s==0) {
340                                         PKG_MEM_ERROR;
341                                         goto error;
342                                 }
343                                 memcpy( ha->sval.s, foo.s, foo.len);
344                                 ha->sval.len = foo.len;
345                                 ha->sval.s[ha->sval.len] = 0;
346                                 if (ha->title.s==0)
347                                         ha->title = ha->sval;
348                         }
349                 } else {
350                         /* element is MSG */
351                         if ( !(foo.len==ELEM_VAL_BODY_LEN &&
352                         !strncasecmp(ELEM_VAL_BODY,foo.s,foo.len)) ) {
353                                 LM_ERR("unsupported value <%.*s> for msg type\n",foo.len,foo.s);
354                                 goto error;
355                         }
356                         app->add_body = 1;
357                         pkg_free( ha );
358                         ha = 0;
359                 }
360
361                 /* parse the element separator, if present */
362                 while( *s && isspace((int)*s) )  s++;
363                 if ( *s && *s!=';')
364                         goto parse_error;
365                 if (*s==';') {
366                         s++;
367                         while( *s && isspace((int)*s) )  s++;
368                         if (!*s)
369                                 goto parse_error;
370                 }
371
372                 /* link the element to tw_append structure */
373                 if (ha) {
374                         if (last==0) {
375                                 last = app->elems = ha;
376                         } else {
377                                 last->next = ha;
378                                 last = ha;
379                         }
380                         ha = NULL;
381                 }
382
383         } /* end while */
384
385         print_tw_append( app );
386         /* free the old string */
387         pkg_free(val);
388         return 0;
389 parse_error:
390         LM_ERR("parse error in <%s> around position %ld\n",
391                         (char*)val, (long)(s-(char*)val));
392 error:
393         if(ha) pkg_free(ha);
394         return -1;
395 }
396
397
398 static struct tw_append *search_tw_append(char *name, int len)
399 {
400         struct tw_append * app;
401
402         for( app=tw_appends ; app ; app=app->next )
403                 if (app->name.len==len && !strncasecmp(app->name.s,name,len) )
404                         return app;
405         return 0;
406 }
407
408
409 int fixup_t_write( void** param, int param_no)
410 {
411         struct tw_info *twi;
412         char *s;
413
414         if (param_no==2) {
415                 twi = (struct tw_info*)pkg_malloc( sizeof(struct tw_info) );
416                 if (twi==0) {
417                         PKG_MEM_ERROR;
418                         return E_OUT_OF_MEM;
419                 }
420                 memset( twi, 0 , sizeof(struct tw_info));
421                 s = (char*)*param;
422                 twi->action.s = s;
423                 if ( (s=strchr(s,'/'))!=0) {
424                         twi->action.len = s - twi->action.s;
425                         if (twi->action.len==0) {
426                                 LM_ERR("empty action name\n");
427                                 pkg_free(twi);
428                                 return E_CFG;
429                         }
430                         s++;
431                         if (*s==0) {
432                                 LM_ERR("empty append name\n");
433                                 pkg_free(twi);
434                                 return E_CFG;
435                         }
436                         twi->append = search_tw_append( s, strlen(s));
437                         if (twi->append==0) {
438                                 LM_ERR("unknown append name <%s>\n",s);
439                                 pkg_free(twi);
440                                 return E_CFG;
441                         }
442                 } else {
443                         twi->action.len = strlen(twi->action.s);
444                 }
445                 *param=(void*)twi;
446         }
447
448         return 0;
449 }
450
451
452 int init_twrite_sock(void)
453 {
454         int flags;
455
456         sock = socket(PF_LOCAL, SOCK_DGRAM, 0);
457         if (sock == -1) {
458                 LM_ERR("unable to create socket: %s\n", strerror(errno));
459                 return -1;
460         }
461
462         /* Turn non-blocking mode on */
463         flags = fcntl(sock, F_GETFL);
464         if (flags == -1){
465                 LM_ERR("fcntl failed: %s\n", strerror(errno));
466                 close(sock);
467                 return -1;
468         }
469
470         if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1) {
471                 LM_ERR("fcntl: set non-blocking failed: %s\n", strerror(errno));
472                 close(sock);
473                 return -1;
474         }
475         return 0;
476 }
477
478
479 int init_twrite_lines()
480 {
481         int i;
482
483         /* init the line table */
484         for(i=0;i<TWRITE_PARAMS;i++) {
485                 iov_lines_eol[2*i].iov_base = 0;
486                 iov_lines_eol[2*i].iov_len = 0;
487                 iov_lines_eol[2*i+1] = eol;
488         }
489
490         /* first line is the version - fill it now */
491         eol_line_s(0)   = TWRITE_VERSION_S;
492         eol_line_len(0) = TWRITE_VERSION_LEN;
493
494         return 0;
495 }
496
497
498 static int inline write_to_fifo(char *fifo, int cnt )
499 {
500         int   fd_fifo;
501
502         /* open FIFO file stream */
503         if((fd_fifo = open(fifo,O_WRONLY | O_NONBLOCK)) == -1){
504                 switch(errno){
505                         case ENXIO:
506                                 LM_ERR("cannot open fifo file - nobody listening for reading"
507                                         " [%s] (%s)\n", fifo, strerror(errno));
508                                 break;
509                         default:
510                                 LM_ERR("failed to open [%s] fifo: %s\n", fifo, strerror(errno));
511                 }
512                 goto error;
513         }
514
515         /* write now (unbuffered straight-down write) */
516 repeat:
517         if (writev(fd_fifo, iov_lines_eol, 2*cnt)<0) {
518                 if (errno!=EINTR) {
519                         LM_ERR("writev failed: %s\n", strerror(errno));
520                         close(fd_fifo);
521                         goto error;
522                 } else {
523                         goto repeat;
524                 }
525         }
526         close(fd_fifo);
527
528         LM_DBG("write completed\n");
529         return 1; /* OK */
530
531 error:
532         return -1;
533 }
534
535
536 static inline char* add2buf(char *buf, char *end, char *title, int title_len,
537                         char *value , int value_len)
538 {
539         if (buf+title_len+value_len+2+1>=end)
540                 return 0;
541         memcpy( buf, title, title_len);
542         buf += title_len;
543         *(buf++) = ':';
544         *(buf++) = ' ';
545         memcpy( buf, value, value_len);
546         buf += value_len;
547         *(buf++) = '\n';
548         return buf;
549 }
550
551
552 static inline char* append2buf( char *buf, int len, struct sip_msg *req,
553                         struct hdr_avp *ha)
554 {
555         struct hdr_field *hdr;
556         struct usr_avp   *avp;
557         int_str          avp_val;
558         int_str          avp_name;
559         char  *end;
560         str   foo;
561         int   msg_parsed;
562
563         end = buf+len;
564         msg_parsed = 0;
565
566         while(ha) {
567                 if (ha->type==ELEM_IS_AVP) {
568                         /* search for the AVP */
569                         if (ha->sval.s) {
570                                 avp_name.s=ha->sval;
571                                 avp = search_first_avp( AVP_NAME_STR, avp_name, &avp_val, 0);
572                                 LM_DBG("AVP <%.*s>: %p\n",avp_name.s.len, avp_name.s.s, avp);
573                         } else {
574                                 avp_name.n=ha->ival;
575                                 avp = search_first_avp( 0, avp_name, &avp_val, 0);
576                                 LM_DBG("AVP <%i>: %p\n",avp_name.n,avp);
577                         }
578                         if (avp) {
579                                 if (avp->flags&AVP_VAL_STR) {
580                                         buf=add2buf( buf, end, ha->title.s, ha->title.len,
581                                                 avp_val.s.s , avp_val.s.len);
582                                         if (!buf)
583                                                 goto overflow_err;
584                                 } else {
585                                         foo.s=int2str( (unsigned long)avp_val.n, &foo.len);
586                                         buf=add2buf( buf, end, ha->title.s, ha->title.len,
587                                                 foo.s , foo.len);
588                                         if (!buf)
589                                                 goto overflow_err;
590                                 }
591                         }
592                 } else if (ha->type==ELEM_IS_HDR) {
593                         /* parse the HDRs */
594                         if (!msg_parsed) {
595                                 if (parse_headers( req, HDR_EOH_F, 0)!=0) {
596                                         LM_ERR("parsing hdrs failed\n");
597                                         goto error;
598                                 }
599                                 msg_parsed = 1;
600                         }
601                         /* search the HDR */
602                         if (ha->ival==HDR_OTHER_T) {
603                                 for(hdr=req->headers;hdr;hdr=hdr->next)
604                                         if (ha->sval.len==hdr->name.len &&
605                                         strncasecmp( ha->sval.s, hdr->name.s, hdr->name.len)==0)
606                                                 break;
607                         } else {
608                                 for(hdr=req->headers;hdr;hdr=hdr->next)
609                                         if (ha->ival==hdr->type)
610                                                 break;
611                         }
612                         if (hdr) {
613                                 trim_len( foo.len, foo.s, hdr->body);
614                                 buf=add2buf( buf, end, ha->title.s, ha->title.len,
615                                         foo.s , foo.len);
616                                 if (!buf)
617                                         goto overflow_err;
618                         }
619                 } else {
620                         LM_ERR("BUG: unknown element type %d\n", ha->type);
621                         goto error;
622                 }
623
624                 ha = ha->next;
625         }
626
627         return buf;
628 overflow_err:
629         LM_ERR("overflow -> append exceeded %d len\n",len);
630 error:
631         return 0;
632 }
633
634
635 static int assemble_msg(struct sip_msg* msg, struct tw_info *twi)
636 {
637         static char     id_buf[IDBUF_LEN];
638         static char     route_buffer[ROUTE_BUFFER_MAX];
639         static char     append_buf[APPEND_BUFFER_MAX];
640         static char     cmd_buf[CMD_BUFFER_MAX];
641         static str      empty_param = STR_STATIC_INIT(".");
642         unsigned int      hash_index, label;
643         contact_body_t*   cb=0;
644         contact_t*        c=0;
645         name_addr_t       na;
646         rr_t*             record_route;
647         struct hdr_field* p_hdr;
648         param_hooks_t     hooks;
649         int               l;
650         char*             s, fproxy_lr;
651         int               first_rr;
652         str               route, next_hop, append, tmp_s, body, str_uri;
653
654         if(msg->first_line.type != SIP_REQUEST){
655                 LM_ERR("called for something else thena SIP request\n");
656                 goto error;
657         }
658
659         /* parse all -- we will need every header field for a UAS */
660         if ( parse_headers(msg, HDR_EOH_F, 0)==-1) {
661                 LM_ERR("parse_headers failed\n");
662                 goto error;
663         }
664
665         /* find index and hash; (the transaction can be safely used due
666          * to refcounting till script completes) */
667         if( t_get_trans_ident(msg,&hash_index,&label) == -1 ) {
668                 LM_ERR("assemble_msg: t_get_trans_ident failed\n");
669                 goto error;
670         }
671
672         /* parse from header */
673         if (msg->from==0 || (msg->from->parsed==0 && parse_from_header(msg)==-1)) {
674                 LM_ERR("while parsing <From:> header\n");
675                 goto error;
676         }
677
678         /* parse the RURI (doesn't make any malloc) */
679         msg->parsed_uri_ok = 0; /* force parsing */
680         if (parse_sip_msg_uri(msg)<0) {
681                 LM_ERR("uri has not been parsed\n");
682                 goto error;
683         }
684
685         /* parse contact header */
686         str_uri.s = 0;
687         str_uri.len = 0;
688         if(msg->contact) {
689                 if (msg->contact->parsed==0 && parse_contact(msg->contact)==-1) {
690                         LM_ERR("error while parsing 'Contact' header\n");
691                         goto error;
692                 }
693                 cb = (contact_body_t*)msg->contact->parsed;
694                 if(cb && (c=cb->contacts)) {
695                         str_uri = c->uri;
696                         if (find_not_quoted(&str_uri,'<')) {
697                                 parse_nameaddr(&str_uri,&na);
698                                 str_uri = na.uri;
699                         }
700                 }
701         }
702
703         /* str_uri is taken from caller's contact or from header
704          * for backwards compatibility with pre-3261 (from is already parsed)*/
705         if(!str_uri.len || !str_uri.s)
706                 str_uri = get_from(msg)->uri;
707
708         /* parse Record-Route headers */
709         route.s = s = route_buffer; route.len = 0;
710         fproxy_lr = 0;
711         next_hop = empty_param;
712
713         p_hdr = msg->record_route;
714         if(p_hdr) {
715                 if (p_hdr->parsed==0 && parse_rr(p_hdr)!=0 ) {
716                         LM_ERR("while parsing 'Record-Route' header\n");
717                         goto error;
718                 }
719                 record_route = (rr_t*)p_hdr->parsed;
720         } else {
721                 record_route = 0;
722         }
723
724         first_rr = 1;
725
726         if( record_route ) {
727                 if ( (tmp_s.s=find_not_quoted(&record_route->nameaddr.uri,';'))!=0 &&
728                 tmp_s.s+1!=record_route->nameaddr.uri.s+
729                 record_route->nameaddr.uri.len) {
730                         /* Parse all parameters */
731                         tmp_s.len = record_route->nameaddr.uri.len - (tmp_s.s-
732                                 record_route->nameaddr.uri.s);
733                         if (parse_params( &tmp_s, CLASS_URI, &hooks,
734                         &record_route->params) < 0) {
735                                 LM_ERR("error while parsing record route uri params\n");
736                                 goto error;
737                         }
738                         fproxy_lr = (hooks.uri.lr != 0);
739                         LM_DBG("record_route->nameaddr.uri: %.*s\n",
740                                 record_route->nameaddr.uri.len,record_route->nameaddr.uri.s);
741                         if(fproxy_lr){
742                                 first_rr = 0;
743                                 LM_DBG("first proxy has loose routing.\n");
744                                 copy_route(s,route.len,record_route->nameaddr.uri.s,
745                                         record_route->nameaddr.uri.len);
746                         }
747                 }
748                 for(;p_hdr;p_hdr = p_hdr->next) {
749                         /* filter out non-RR hdr and empty hdrs */
750                         if( (p_hdr->type!=HDR_RECORDROUTE_T) || p_hdr->body.len==0)
751                                 continue;
752
753                         if(p_hdr->parsed==0 && parse_rr(p_hdr)!=0 ){
754                                 LM_ERR("while parsing 'Record-route' header\n");
755                                 goto error;
756                         }
757                         for(record_route=p_hdr->parsed; record_route;
758                                                 record_route=record_route->next){
759                                 LM_DBG("record_route->nameaddr.uri: <%.*s>\n",
760                                                 record_route->nameaddr.uri.len,
761                                                 record_route->nameaddr.uri.s);
762                                 if (!first_rr) {
763                                         copy_route(s,route.len,record_route->nameaddr.uri.s,
764                                                         record_route->nameaddr.uri.len);
765                                 }
766                                 first_rr=0;
767                         }
768                 }
769
770                 if(!fproxy_lr){
771                         copy_route(s,route.len,str_uri.s,str_uri.len);
772                         str_uri = ((rr_t*)msg->record_route->parsed)->nameaddr.uri;
773                 } else {
774                         next_hop = ((rr_t*)msg->record_route->parsed)->nameaddr.uri;
775                 }
776         }
777
778         LM_DBG("calculated route: %.*s\n", route.len,route.len ? route.s : "");
779         LM_DBG("next r-uri: %.*s\n", str_uri.len,str_uri.len ? str_uri.s : "");
780
781         if ( REQ_LINE(msg).method_value==METHOD_INVITE ||
782                         REQ_LINE(msg).method_value==METHOD_INFO ||
783                         (twi->append && twi->append->add_body) ) {
784                 /* get body */
785                 if( (body.s = get_body(msg)) == 0 ){
786                         LM_ERR("get_body failed\n");
787                         goto error;
788                 }
789                 body.len = msg->len - (body.s - msg->buf);
790         } else {
791                 body = empty_param;
792         }
793
794         /* additional headers */
795         append.s = s = append_buf;
796         if (sizeof(flag_t)*2+12+1 >= APPEND_BUFFER_MAX) {
797                 LM_ERR("buffer overflow while copying optional header\n");
798                 goto error;
799         }
800         append_str(s,"P-MsgFlags: ",12);
801         l = APPEND_BUFFER_MAX - (12+1); /* include trailing `\n'*/
802
803         if (int2reverse_hex(&s, &l, (int)msg->msg_flags) == -1) {
804                 LM_ERR("buffer overflow while copying optional header\n");
805                 goto error;
806         }
807         append_chr(s,'\n');
808
809         if ( twi->append && ((s=append2buf( s, APPEND_BUFFER_MAX-(s-append.s), msg,
810         twi->append->elems))==0) )
811                 goto error;
812
813         /* body separator */
814         append_chr(s,'.');
815         append.len = s-append.s;
816
817         eol_line_s(1) = s = cmd_buf;
818         if(twi->action.len+12 >= CMD_BUFFER_MAX){
819                 LM_ERR("buffer overflow while copying command name\n");
820                 goto error;
821         }
822         append_str(s,"sip_request.",12);
823         append_str(s,twi->action.s, twi->action.len);
824         eol_line_len(1) = s - (char*)eol_line_s(1);
825
826         eol_line(2,REQ_LINE(msg).method);     /* method type */
827         eol_line(3,msg->parsed_uri.user);     /* user from r-uri */
828         eol_line(4,msg->parsed_uri.host);     /* domain */
829
830         eol_line(5,msg->rcv.bind_address->address_str); /* dst ip */
831
832         eol_line(6,msg->rcv.dst_port==SIP_PORT ?
833                         empty_param : msg->rcv.bind_address->port_no_str); /* port */
834
835         /* r_uri ('Contact:' for next requests) */
836         eol_line(7,msg->first_line.u.request.uri);
837
838         /* r_uri for subsequent requests */
839         eol_line(8,str_uri.len?str_uri:empty_param);
840
841         eol_line(9,get_from(msg)->body);                /* from */
842         eol_line(10,msg->to->body);                     /* to */
843         eol_line(11,msg->callid->body);         /* callid */
844         eol_line(12,get_from(msg)->tag_value);  /* from tag */
845         eol_line(13,get_to(msg)->tag_value);    /* to tag */
846         eol_line(14,get_cseq(msg)->number);     /* cseq number */
847
848         eol_line_s(15)=id_buf;       /* hash:label */
849         s = int2str(hash_index, &l);
850         if (l+1>=IDBUF_LEN) {
851                 LM_ERR("too big hash\n");
852                 goto error;
853         }
854         memcpy(id_buf, s, l);
855         id_buf[l]=':';
856         eol_line_len(15)=l+1;
857         s = int2str(label, &l);
858         if (l+1+eol_line_len(15)>=IDBUF_LEN) {
859                 LM_ERR("too big label\n");
860                 goto error;
861         }
862         memcpy(id_buf+eol_line_len(15), s, l);
863         eol_line_len(15) += l;
864
865         eol_line(16, route.len ? route : empty_param );
866         eol_line(17, next_hop );
867         eol_line(18, append );
868         eol_line(19, body );
869
870         /* success */
871         return 1;
872 error:
873         /* 0 would lead to immediate script exit -- -1 returns
874          * with 'false' to script processing */
875         return -1;
876 }
877
878
879 static int write_to_unixsock(char* sockname, int cnt)
880 {
881         int len, e;
882         struct sockaddr_un dest;
883
884         if (!sockname) {
885                 LM_ERR("Invalid parameter\n");
886                 return E_UNSPEC;
887         }
888
889         len = strlen(sockname);
890         if (len == 0) {
891                 LM_DBG("Error - empty socket name\n");
892                 return -1;
893         } else if (len > 107) {
894                 LM_ERR("Socket name too long\n");
895                 return -1;
896         }
897
898         memset(&dest, 0, sizeof(dest));
899         dest.sun_family = PF_LOCAL;
900         memcpy(dest.sun_path, sockname, len);
901 #ifdef HAVE_SOCKADDR_SA_LEN
902         dest.sun_len = len;
903 #endif
904
905         e = connect(sock, (struct sockaddr*)&dest, SUN_LEN(&dest));
906 #ifdef HAVE_CONNECT_ECONNRESET_BUG
907         /*
908          * Workaround for a nasty bug in BSD kernels dated back
909          * to the Berkeley days, so that can be found in many modern
910          * BSD-derived kernels. Workaround should be pretty harmless since
911          * in normal conditions connect(2) can never return ECONNRESET.
912          */
913         if ((e == -1) && (errno == ECONNRESET))
914                 e = 0;
915 #endif
916         if (e == -1) {
917                 LM_ERR("error in connect: %s\n", strerror(errno));
918                 return -1;
919         }
920
921         if (tsend_dgram_ev(sock, iov_lines_eol, 2 * cnt,
922                         cfg_get(tm, tm_cfg, tm_unix_tx_timeout)) < 0) {
923                 LM_ERR("writev failed: %s\n", strerror(errno));
924                 return -1;
925         }
926
927         return 0;
928 }
929
930
931 int t_write_req(struct sip_msg* msg, char* vm_fifo, char* info)
932 {
933         if (assemble_msg(msg, (struct tw_info*)info) < 0) {
934                 LM_ERR("error int assemble_msg\n");
935                 return -1;
936         }
937
938         if (write_to_fifo(vm_fifo, TWRITE_PARAMS) == -1) {
939                 LM_ERR("write_to_fifo failed\n");
940                 return -1;
941         }
942
943         /* make sure that if voicemail does not initiate a reply
944          * timely, a SIP timeout will be sent out */
945         if (add_blind_uac() == -1) {
946                 LM_ERR("add_blind failed\n");
947                 return -1;
948         }
949         return 1;
950 }
951
952
953 int t_write_unix(struct sip_msg* msg, char* socket, char* info)
954 {
955         if (assemble_msg(msg, (struct tw_info*)info) < 0) {
956                 LM_ERR("error in assemble_msg\n");
957                 return -1;
958         }
959
960         if (write_to_unixsock(socket, TWRITE_PARAMS) == -1) {
961                 LM_ERR("write_to_unixsock failed\n");
962                 return -1;
963         }
964
965         /* make sure that if voicemail does not initiate a reply
966          * timely, a SIP timeout will be sent out */
967         if (add_blind_uac() == -1) {
968                 LM_ERR("add_blind failed\n");
969                 return -1;
970         }
971         return 1;
972 }