00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include <sys/types.h>
00040 #include <sys/stat.h>
00041 #include <fcntl.h>
00042 #include <errno.h>
00043 #include <string.h>
00044 #include <sys/uio.h>
00045 #include <unistd.h>
00046 #include <fcntl.h>
00047 #include <sys/un.h>
00048 #include <ctype.h>
00049 #include <string.h>
00050
00051 #include "../../str.h"
00052 #include "../../ut.h"
00053 #include "../../dprint.h"
00054 #include "../../pvar.h"
00055 #include "../../mem/mem.h"
00056 #include "../../parser/parser_f.h"
00057 #include "../../parser/parse_from.h"
00058 #include "../../parser/parse_rr.h"
00059 #include "../../parser/contact/parse_contact.h"
00060 #include "../../tsend.h"
00061 #include "t_lookup.h"
00062 #include "t_fwd.h"
00063 #include "t_fifo.h"
00064
00065
00066
00067 #if !defined(AF_LOCAL)
00068 #define AF_LOCAL AF_UNIX
00069 #endif
00070 #if !defined(PF_LOCAL)
00071 #define PF_LOCAL PF_UNIX
00072 #endif
00073
00074
00075
00076 #ifndef SUN_LEN
00077 #define SUN_LEN(sa) ( strlen((sa)->sun_path) + \
00078 (size_t)(((struct sockaddr_un*)0)->sun_path) )
00079 #endif
00080
00081 int tm_unix_tx_timeout = 2;
00082
00083 #define TWRITE_PARAMS 20
00084 #define TWRITE_VERSION_S "0.3"
00085 #define TWRITE_VERSION_LEN (sizeof(TWRITE_VERSION_S)-1)
00086 #define eol_line(_i_) ( lines_eol[2*(_i_)] )
00087
00088 #define IDBUF_LEN 128
00089 #define ROUTE_BUFFER_MAX 512
00090 #define APPEND_BUFFER_MAX 4096
00091 #define CMD_BUFFER_MAX 128
00092
00093 #define copy_route(s,len,rs,rlen) \
00094 do {\
00095 if(rlen+len+3 >= ROUTE_BUFFER_MAX){\
00096 LM_ERR("buffer overflow while copying new route\n");\
00097 return -1;\
00098 }\
00099 if(len){\
00100 append_chr(s,','); len++;\
00101 }\
00102 append_chr(s,'<');len++;\
00103 append_str(s,rs,rlen);\
00104 len += rlen; \
00105 append_chr(s,'>');len++;\
00106 } while(0)
00107
00108 static str lines_eol[2*TWRITE_PARAMS];
00109 static str eol={"\n",1};
00110
00111 static int sock;
00112
00113 struct append_elem {
00114 str name;
00115 pv_spec_t spec;
00116 struct append_elem *next;
00117 };
00118
00119 struct tw_append {
00120 str name;
00121 int add_body;
00122 struct append_elem *elems;
00123 struct tw_append *next;
00124 };
00125
00126 struct tw_info {
00127 str action;
00128 struct tw_append *append;
00129 };
00130
00131 static struct tw_append *tw_appends;
00132
00133
00134
00135
00136
00137
00138
00139 int parse_tw_append( modparam_t type, void* val)
00140 {
00141 struct append_elem *last;
00142 struct append_elem *elem;
00143 struct tw_append *app;
00144 pv_spec_t lspec;
00145 char *s;
00146 str foo;
00147 str bar;
00148
00149
00150 if (val==0 || ((char*)val)[0]==0)
00151 return 0;
00152
00153 s = (char*)val;
00154
00155
00156 while( *s && isspace((int)*s) ) s++;
00157 if ( !*s || *s==':')
00158 goto parse_error;
00159 foo.s = s;
00160 while ( *s && *s!=':' && !isspace((int)*s) ) s++;
00161 if ( !*s || foo.s==s )
00162 goto parse_error;
00163 foo.len = s - foo.s;
00164
00165 while( *s && isspace((int)*s) ) s++;
00166 if ( !*s || *s!=':')
00167 goto parse_error;
00168 s++;
00169
00170
00171 for(app=tw_appends;app;app=app->next)
00172 if (app->name.len==foo.len && !strncasecmp(app->name.s,foo.s,foo.len)){
00173 LM_ERR("duplicated tw_append name <%.*s>\n",foo.len,foo.s);
00174 goto error;
00175 }
00176
00177
00178 app = (struct tw_append*)pkg_malloc( sizeof(struct tw_append) );
00179 if (app==0) {
00180 LM_ERR("no more pkg memory\n");
00181 goto error;
00182 }
00183
00184
00185 app->name = foo;
00186 last = app->elems = 0;
00187
00188
00189 app->next = tw_appends;
00190 tw_appends = app;
00191
00192
00193 while (*s) {
00194
00195
00196 while( *s && isspace((int)*s) ) s++;
00197 if ( !*s )
00198 goto parse_error;
00199
00200 foo.s = s;
00201 while( *s && *s!='=' && *s!=';' && !isspace((int)*s) ) s++;
00202 if (foo.s==s)
00203 goto parse_error;
00204 foo.len = s - foo.s;
00205
00206 while( *s && isspace((int)*s) ) s++;
00207 if ( *s && *s!='=' && *s!=';' )
00208 goto parse_error;
00209
00210
00211 if (*s=='=' ) {
00212
00213 s++;
00214
00215
00216 elem = (struct append_elem*)pkg_malloc(sizeof(struct append_elem));
00217 if (elem==0) {
00218 LM_ERR("no more pkg memory\n");
00219 goto error;
00220 }
00221 memset( elem, 0, sizeof(struct append_elem));
00222
00223
00224 elem->name = foo;
00225 if (last==0) {
00226 app->elems = elem;
00227 } else {
00228 last->next = elem;
00229 }
00230 last = elem;
00231
00232
00233 while (*s && isspace((int)*s))
00234 s++;
00235 } else {
00236
00237 s = foo.s;
00238 elem = 0;
00239 }
00240
00241
00242 bar.s = s; bar.len = strlen(bar.s);
00243 if ( (foo.s=pv_parse_spec( &bar, &lspec))==0 )
00244 goto parse_error;
00245
00246
00247 if (elem==0) {
00248 if (lspec.type!=PVT_MSG_BODY) {
00249 LM_ERR("short spec '%.*s' unknown(aceepted only body)\n",
00250 (int)(long)(foo.s-s), s);
00251 goto error;
00252 }
00253 app->add_body = 1;
00254 } else {
00255 elem->spec = lspec;
00256 }
00257
00258
00259 s = foo.s;
00260
00261
00262 while (*s && isspace((int)*s)) s++;
00263 if (*s && *(s++)!=';')
00264 goto parse_error;
00265 }
00266
00267
00268 for( elem=app->elems ; elem ; elem=elem->next)
00269 elem->name.s[elem->name.len] = 0;
00270
00271 app->name.s[app->name.len] = 0;
00272
00273 return 0;
00274 parse_error:
00275 LM_ERR("parse error in <%s> around position %ld(%c)\n",
00276 (char*)val, (long)(s-(char*)val),*s);
00277 error:
00278 return -1;
00279 }
00280
00281
00282 static struct tw_append *search_tw_append(char *name, int len)
00283 {
00284 struct tw_append * app;
00285
00286 for( app=tw_appends ; app ; app=app->next )
00287 if (app->name.len==len && !strncasecmp(app->name.s,name,len) )
00288 return app;
00289 return 0;
00290 }
00291
00292
00293 int fixup_t_write( void** param, int param_no)
00294 {
00295 struct tw_info *twi;
00296 char *s;
00297
00298 if (param_no==2) {
00299 twi = (struct tw_info*)pkg_malloc( sizeof(struct tw_info) );
00300 if (twi==0) {
00301 LM_ERR("no more pkg memory\n");
00302 return E_OUT_OF_MEM;
00303 }
00304 memset( twi, 0 , sizeof(struct tw_info));
00305 s = (char*)*param;
00306 twi->action.s = s;
00307 if ( (s=strchr(s,'/'))!=0) {
00308 twi->action.len = s - twi->action.s;
00309 if (twi->action.len==0) {
00310 LM_ERR("empty action name\n");
00311 return E_CFG;
00312 }
00313 s++;
00314 if (*s==0) {
00315 LM_ERR("empty append name\n");
00316 return E_CFG;
00317 }
00318 twi->append = search_tw_append( s, strlen(s));
00319 if (twi->append==0) {
00320 LM_ERR("unknown append name <%s>\n",s);
00321 return E_CFG;
00322 }
00323 } else {
00324 twi->action.len = strlen(twi->action.s);
00325 }
00326 *param=(void*)twi;
00327 }
00328
00329 return 0;
00330 }
00331
00332
00333
00334 int init_twrite_sock(void)
00335 {
00336 int flags;
00337
00338 sock = socket(PF_LOCAL, SOCK_DGRAM, 0);
00339 if (sock == -1) {
00340 LM_ERR("unable to create socket: %s\n", strerror(errno));
00341 return -1;
00342 }
00343
00344
00345 flags = fcntl(sock, F_GETFL);
00346 if (flags == -1){
00347 LM_ERR("init_twrite_sock: fcntl failed: %s\n", strerror(errno));
00348 close(sock);
00349 return -1;
00350 }
00351
00352 if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1) {
00353 LM_ERR("init_twrite_sock: fcntl: set non-blocking failed:"
00354 " %s\n", strerror(errno));
00355 close(sock);
00356 return -1;
00357 }
00358 return 0;
00359 }
00360
00361
00362
00363 int init_twrite_lines(void)
00364 {
00365 int i;
00366
00367
00368 for(i=0;i<TWRITE_PARAMS;i++) {
00369 lines_eol[2*i].s = 0;
00370 lines_eol[2*i].len = 0;
00371 lines_eol[2*i+1] = eol;
00372 }
00373
00374
00375 eol_line(0).s = TWRITE_VERSION_S;
00376 eol_line(0).len = TWRITE_VERSION_LEN;
00377
00378 return 0;
00379 }
00380
00381
00382
00383 static inline int write_to_fifo(char *fifo, int cnt )
00384 {
00385 int fd_fifo;
00386
00387
00388 if((fd_fifo = open(fifo,O_WRONLY | O_NONBLOCK)) == -1){
00389 switch(errno){
00390 case ENXIO:
00391 LM_ERR("nobody listening on [%s] fifo for reading!\n",fifo);
00392 default:
00393 LM_ERR("failed to open [%s] fifo : %s\n", fifo,
00394 strerror(errno));
00395 }
00396 goto error;
00397 }
00398
00399
00400 repeat:
00401 if (writev(fd_fifo, (struct iovec*)(void*)lines_eol, 2*cnt)<0) {
00402 if (errno!=EINTR) {
00403 LM_ERR("writev failed: %s\n", strerror(errno));
00404 close(fd_fifo);
00405 goto error;
00406 } else {
00407 goto repeat;
00408 }
00409 }
00410 close(fd_fifo);
00411
00412 LM_DBG("write completed\n");
00413 return 1;
00414
00415 error:
00416 return -1;
00417 }
00418
00419
00420
00421 static inline char* add2buf(char *buf, char *end, str *name, str *value)
00422 {
00423 if (buf+name->len+value->len+2+1>=end)
00424 return 0;
00425 memcpy( buf, name->s, name->len);
00426 buf += name->len;
00427 *(buf++) = ':';
00428 *(buf++) = ' ';
00429 memcpy( buf, value->s, value->len);
00430 buf += value->len;
00431 *(buf++) = '\n';
00432 return buf;
00433 }
00434
00435
00436
00437 static inline char* append2buf( char *buf, int len, struct sip_msg *req,
00438 struct append_elem *elem)
00439 {
00440 pv_value_t value;
00441 char *end;
00442
00443 end = buf+len;
00444
00445 while (elem)
00446 {
00447
00448 if (pv_get_spec_value(req, &elem->spec, &value)!=0)
00449 {
00450 LM_ERR("failed to get '%.*s'\n", elem->name.len,elem->name.s);
00451 }
00452
00453
00454 if ( !(value.flags&PV_VAL_NULL) ) {
00455
00456 buf = add2buf( buf, end, &elem->name, &value.rs);
00457 if (!buf)
00458 {
00459 LM_ERR("overflow -> append exceeded %d len\n",len);
00460 return 0;
00461 }
00462 }
00463
00464 elem = elem->next;
00465 }
00466
00467 return buf;
00468 }
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478 static int assemble_msg(struct sip_msg* msg, struct tw_info *twi)
00479 {
00480 static char id_buf[IDBUF_LEN];
00481 static char route_buffer[ROUTE_BUFFER_MAX];
00482 static char append_buf[APPEND_BUFFER_MAX];
00483 static char cmd_buf[CMD_BUFFER_MAX];
00484 static str empty_param = {".",1};
00485 unsigned int hash_index, label;
00486 contact_body_t* cb=0;
00487 contact_t* c=0;
00488 name_addr_t na;
00489 rr_t* record_route;
00490 struct hdr_field* p_hdr;
00491 param_hooks_t hooks;
00492 int l;
00493 char* s, fproxy_lr;
00494 str route, next_hop, append, tmp_s, body, str_uri;
00495
00496 if(msg->first_line.type != SIP_REQUEST){
00497 LM_ERR("called for something else then a SIP request\n");
00498 return -1;
00499 }
00500
00501
00502 if ( parse_headers(msg, HDR_EOH_F, 0)==-1) {
00503 LM_ERR("parse_headers failed\n");
00504 return -1;
00505 }
00506
00507
00508
00509 if( t_get_trans_ident(msg,&hash_index,&label) == -1 ) {
00510 LM_ERR("t_get_trans_ident failed\n");
00511 return -1;
00512 }
00513
00514
00515 if (msg->from->parsed==0 && parse_from_header(msg)<0 ) {
00516 LM_ERR("failed to parse <From:> header\n");
00517 return -1;
00518 }
00519
00520
00521 msg->parsed_uri_ok = 0;
00522 if (parse_sip_msg_uri(msg)<0) {
00523 LM_ERR("uri has not been parsed\n");
00524 return -1;
00525 }
00526
00527
00528 str_uri.s = 0;
00529 str_uri.len = 0;
00530 if(msg->contact) {
00531 if (msg->contact->parsed==0 && parse_contact(msg->contact)<0) {
00532 LM_ERR("failed to parse <Contact:> header\n");
00533 return -1;
00534 }
00535 cb = (contact_body_t*)msg->contact->parsed;
00536 if(cb && (c=cb->contacts)) {
00537 str_uri = c->uri;
00538 if (find_not_quoted(&str_uri,'<')) {
00539 parse_nameaddr(&str_uri,&na);
00540 str_uri = na.uri;
00541 }
00542 }
00543 }
00544
00545
00546
00547 if(!str_uri.len || !str_uri.s)
00548 str_uri = get_from(msg)->uri;
00549
00550
00551 route.s = s = route_buffer; route.len = 0;
00552 fproxy_lr = 0;
00553 next_hop = empty_param;
00554
00555 p_hdr = msg->record_route;
00556 if(p_hdr) {
00557 if (p_hdr->parsed==0 && parse_rr(p_hdr)!=0 ) {
00558 LM_ERR("failed to parse 'Record-Route:' header\n");
00559 return -1;
00560 }
00561 record_route = (rr_t*)p_hdr->parsed;
00562 } else {
00563 record_route = 0;
00564 }
00565
00566 if( record_route ) {
00567 if ( (tmp_s.s=find_not_quoted(&record_route->nameaddr.uri,';'))!=0 &&
00568 tmp_s.s+1!=record_route->nameaddr.uri.s+
00569 record_route->nameaddr.uri.len) {
00570
00571 tmp_s.len = record_route->nameaddr.uri.len - (tmp_s.s-
00572 record_route->nameaddr.uri.s);
00573 if (parse_params( &tmp_s, CLASS_URI, &hooks,
00574 &record_route->params) < 0) {
00575 LM_ERR("failed to parse record route uri params\n");
00576 return -1;
00577 }
00578 fproxy_lr = (hooks.uri.lr != 0);
00579 LM_DBG("record_route->nameaddr.uri: %.*s\n",
00580 record_route->nameaddr.uri.len,record_route->nameaddr.uri.s);
00581 if(fproxy_lr){
00582 LM_DBG("first proxy has loose routing\n");
00583 copy_route(s,route.len,record_route->nameaddr.uri.s,
00584 record_route->nameaddr.uri.len);
00585 }
00586 }
00587 for(p_hdr = p_hdr->next;p_hdr;p_hdr = p_hdr->next) {
00588
00589 if( (p_hdr->type!=HDR_RECORDROUTE_T) || p_hdr->body.len==0)
00590 continue;
00591
00592 if(p_hdr->parsed==0 && parse_rr(p_hdr)!=0 ){
00593 LM_ERR("failed to parse <Record-route:> header\n");
00594 return -1;
00595 }
00596 for(record_route=p_hdr->parsed; record_route;
00597 record_route=record_route->next){
00598 LM_DBG("record_route->nameaddr.uri: <%.*s>\n",
00599 record_route->nameaddr.uri.len,
00600 record_route->nameaddr.uri.s);
00601 copy_route(s,route.len,record_route->nameaddr.uri.s,
00602 record_route->nameaddr.uri.len);
00603 }
00604 }
00605
00606 if(!fproxy_lr){
00607 copy_route(s,route.len,str_uri.s,str_uri.len);
00608 str_uri = ((rr_t*)msg->record_route->parsed)->nameaddr.uri;
00609 } else {
00610 next_hop = ((rr_t*)msg->record_route->parsed)->nameaddr.uri;
00611 }
00612 }
00613
00614 LM_DBG("calculated route: %.*s\n",route.len,route.len ? route.s : "");
00615 LM_DBG("next r-uri: %.*s\n",str_uri.len,str_uri.len ? str_uri.s : "");
00616
00617 if ( REQ_LINE(msg).method_value==METHOD_INVITE ||
00618 (twi->append && twi->append->add_body) ) {
00619
00620 if( (body.s = get_body(msg)) == 0 ){
00621 LM_ERR("get_body failed\n");
00622 return -1;
00623 }
00624 body.len = msg->len - (body.s - msg->buf);
00625 } else {
00626 body = empty_param;
00627 }
00628
00629
00630 append.s = s = append_buf;
00631 if (sizeof(flag_t)*2+12+1 >= APPEND_BUFFER_MAX) {
00632 LM_ERR("buffer overflow while copying flags\n");
00633 return -1;
00634 }
00635 append_str(s,"P-MsgFlags: ",12);
00636 l = APPEND_BUFFER_MAX - (12+1);
00637
00638 if (int2reverse_hex(&s, &l, (int)msg->msg_flags) == -1) {
00639 LM_ERR("buffer overflow while copying optional header\n");
00640 return -1;
00641 }
00642 append_chr(s,'\n');
00643
00644 if ( twi->append && ((s=append2buf( s, APPEND_BUFFER_MAX-(s-append.s), msg,
00645 twi->append->elems))==0) )
00646 return -1;
00647
00648
00649 append_chr(s,'.');
00650 append.len = s-append.s;
00651
00652 eol_line(1).s = s = cmd_buf;
00653 if(twi->action.len+12 >= CMD_BUFFER_MAX){
00654 LM_ERR("buffer overflow while copying command name\n");
00655 return -1;
00656 }
00657 append_str(s,"sip_request.",12);
00658 append_str(s,twi->action.s,twi->action.len);
00659 eol_line(1).len = s-eol_line(1).s;
00660
00661 eol_line(2)=REQ_LINE(msg).method;
00662 eol_line(3)=msg->parsed_uri.user;
00663 eol_line(4)=msg->parsed_uri.host;
00664
00665 eol_line(5)=msg->rcv.bind_address->address_str;
00666
00667 eol_line(6)=msg->rcv.dst_port==SIP_PORT ?
00668 empty_param : msg->rcv.bind_address->port_no_str;
00669
00670
00671 eol_line(7)=*GET_RURI(msg);
00672
00673
00674 eol_line(8)=str_uri.len?str_uri:empty_param;
00675
00676 eol_line(9)=get_from(msg)->body;
00677 eol_line(10)=msg->to->body;
00678 eol_line(11)=msg->callid->body;
00679 eol_line(12)=get_from(msg)->tag_value;
00680 eol_line(13)=get_to(msg)->tag_value;
00681 eol_line(14)=get_cseq(msg)->number;
00682
00683 eol_line(15).s=id_buf;
00684 s = int2str(hash_index, &l);
00685 if (l+1>=IDBUF_LEN) {
00686 LM_ERR("too big hash\n");
00687 return -1;
00688 }
00689 memcpy(id_buf, s, l);
00690 id_buf[l]=':';
00691 eol_line(15).len=l+1;
00692 s = int2str(label, &l);
00693 if (l+1+eol_line(15).len>=IDBUF_LEN) {
00694 LM_ERR("too big label\n");
00695 return -1;
00696 }
00697 memcpy(id_buf+eol_line(15).len, s, l);
00698 eol_line(15).len+=l;
00699
00700 eol_line(16) = route.len ? route : empty_param;
00701 eol_line(17) = next_hop;
00702 eol_line(18) = append;
00703 eol_line(19) = body;
00704
00705
00706 return 1;
00707 }
00708
00709
00710 static int write_to_unixsock(char* sockname, int cnt)
00711 {
00712 int len, e;
00713 struct sockaddr_un dest;
00714
00715 if (!sockname) {
00716 LM_ERR("invalid parameter\n");
00717 return E_UNSPEC;
00718 }
00719
00720 len = strlen(sockname);
00721 if (len == 0) {
00722 LM_ERR("empty socket name\n");
00723 return -1;
00724 } else if (len > 107) {
00725 LM_ERR("socket name too long\n");
00726 return -1;
00727 }
00728
00729 memset(&dest, 0, sizeof(dest));
00730 dest.sun_family = PF_LOCAL;
00731 memcpy(dest.sun_path, sockname, len);
00732 #ifdef HAVE_SOCKADDR_SA_LEN
00733 dest.sun_len = len;
00734 #endif
00735
00736 e = connect(sock, (struct sockaddr*)&dest, SUN_LEN(&dest));
00737 #ifdef HAVE_CONNECT_ECONNRESET_BUG
00738
00739
00740
00741
00742
00743
00744 if ((e == -1) && (errno == ECONNRESET))
00745 e = 0;
00746 #endif
00747 if (e == -1) {
00748 LM_ERR("failed to connect: %s\n", strerror(errno));
00749 return -1;
00750 }
00751
00752 if (tsend_dgram_ev(sock, (struct iovec*)(void*)lines_eol, 2 * cnt,
00753 tm_unix_tx_timeout * 1000) < 0) {
00754 LM_ERR("writev failed: %s\n", strerror(errno));
00755 return -1;
00756 }
00757
00758 return 0;
00759 }
00760
00761
00762 int t_write_req(struct sip_msg* msg, char* vm_fifo, char* info)
00763 {
00764 if (assemble_msg(msg, (struct tw_info*)info) < 0) {
00765 LM_ERR("failed to assemble_msg\n");
00766 return -1;
00767 }
00768
00769 if (write_to_fifo(vm_fifo, TWRITE_PARAMS) == -1) {
00770 LM_ERR("write_to_fifo failed\n");
00771 return -1;
00772 }
00773
00774
00775
00776 if (add_blind_uac() == -1) {
00777 LM_ERR("add_blind failed\n");
00778 return -1;
00779 }
00780 return 1;
00781 }
00782
00783
00784 int t_write_unix(struct sip_msg* msg, char* socket, char* info)
00785 {
00786 if (assemble_msg(msg, (struct tw_info*)info) < 0) {
00787 LM_ERR("failed to assemble_msg\n");
00788 return -1;
00789 }
00790
00791 if (write_to_unixsock(socket, TWRITE_PARAMS) == -1) {
00792 LM_ERR("write_to_unixsock failed\n");
00793 return -1;
00794 }
00795
00796
00797
00798 if (add_blind_uac() == -1) {
00799 LM_ERR("add_blind failed\n");
00800 return -1;
00801 }
00802 return 1;
00803 }