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 #include <stdlib.h>
00038 #include "../../parser/parse_from.h"
00039 #include "mi.h"
00040 #include "h_table.h"
00041 #include "t_lookup.h"
00042 #include "t_reply.h"
00043 #include "t_cancel.h"
00044 #include "dlg.h"
00045 #include "callid.h"
00046 #include "uac.h"
00047
00048
00049 struct str_list {
00050 str s;
00051 struct str_list *next;
00052 };
00053
00054
00055 #define skip_hf(_hf) \
00056 (((_hf)->type == HDR_FROM_T) || \
00057 ((_hf)->type == HDR_TO_T) || \
00058 ((_hf)->type == HDR_CALLID_T) || \
00059 ((_hf)->type == HDR_CSEQ_T))
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 static inline struct mi_root* mi_check_msg(struct sip_msg* msg, str* method,
00078 str* body, int* cseq, str* callid)
00079 {
00080 struct cseq_body *parsed_cseq;
00081
00082 if (body && body->len && !msg->content_type)
00083 return init_mi_tree( 400, "Content-Type missing", 19);
00084
00085 if (body && body->len && msg->content_length)
00086 return init_mi_tree( 400, "Content-Length disallowed", 24);
00087
00088 if (!msg->to)
00089 return init_mi_tree( 400, "To missing", 10);
00090
00091 if (!msg->from)
00092 return init_mi_tree( 400, "From missing", 12);
00093
00094
00095 if (parse_from_header(msg) < 0)
00096 return init_mi_tree( 400, "Error in From", 13);
00097
00098 if (msg->cseq && (parsed_cseq = get_cseq(msg))) {
00099 if (str2int( &parsed_cseq->number, (unsigned int*)cseq)!=0)
00100 return init_mi_tree( 400, "Bad CSeq number", 15);
00101
00102 if (parsed_cseq->method.len != method->len
00103 || memcmp(parsed_cseq->method.s, method->s, method->len) !=0 )
00104 return init_mi_tree( 400, "CSeq method mismatch", 20);
00105 } else {
00106 *cseq = -1;
00107 }
00108
00109 if (msg->callid) {
00110 callid->s = msg->callid->body.s;
00111 callid->len = msg->callid->body.len;
00112 } else {
00113 callid->s = 0;
00114 callid->len = 0;
00115 }
00116
00117 return 0;
00118 }
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131 static inline struct str_list *new_str(char *s, int len, struct str_list **last, int *total)
00132 {
00133 struct str_list *new;
00134 new=pkg_malloc(sizeof(struct str_list));
00135 if (!new) {
00136 LM_ERR("no more pkg mem\n");
00137 return 0;
00138 }
00139 new->s.s=s;
00140 new->s.len=len;
00141 new->next=0;
00142
00143 (*last)->next=new;
00144 *last=new;
00145 *total+=len;
00146
00147 return new;
00148 }
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161 static inline char *get_hfblock( str *uri, struct hdr_field *hf, int *l, struct socket_info** send_sock)
00162 {
00163 struct str_list sl, *last, *new, *i, *foo;
00164 int hf_avail, frag_len, total_len;
00165 char *begin, *needle, *dst, *ret, *d;
00166 str *sock_name, *portname;
00167 union sockaddr_union to_su;
00168
00169 ret=0;
00170 total_len=0;
00171 last=&sl;
00172 last->next=0;
00173 portname=sock_name=0;
00174
00175 for (; hf; hf=hf->next) {
00176 if (skip_hf(hf)) continue;
00177
00178 begin=needle=hf->name.s;
00179 hf_avail=hf->len;
00180
00181
00182 while(hf_avail) {
00183 d=memchr(needle, SUBST_CHAR, hf_avail);
00184 if (!d || d+1>=needle+hf_avail) {
00185 new=new_str(begin, hf_avail, &last, &total_len);
00186 if (!new) goto error;
00187 break;
00188 } else {
00189 frag_len=d-begin;
00190 d++;
00191 switch(*d) {
00192 case SUBST_CHAR:
00193
00194 new=new_str(begin, frag_len, &last, &total_len);
00195 if (!new) goto error;
00196
00197 if (!sock_name) {
00198 if (*send_sock==0){
00199 *send_sock=uri2sock(0, uri, &to_su,PROTO_NONE);
00200 if (!*send_sock) {
00201 LM_ERR("send_sock failed\n");
00202 goto error;
00203 }
00204 }
00205 sock_name=&(*send_sock)->address_str;
00206 portname=&(*send_sock)->port_no_str;
00207 }
00208 new=new_str(sock_name->s, sock_name->len,
00209 &last, &total_len );
00210 if (!new) goto error;
00211
00212 new=new_str(":", 1, &last, &total_len);
00213 if (!new) goto error;
00214 new=new_str(portname->s, portname->len,
00215 &last, &total_len );
00216 if (!new) goto error;
00217
00218 begin=needle=d+1;hf_avail-=frag_len+2;
00219 continue;
00220 default:
00221
00222 hf_avail-=frag_len+1;
00223 needle=d;
00224 }
00225 }
00226 }
00227
00228
00229
00230 LM_DBG("one more hf processed\n");
00231 }
00232
00233
00234
00235 ret=pkg_malloc(total_len);
00236 if (!ret) {
00237 LM_ERR("no pkg mem for hf block\n");
00238 goto error;
00239 }
00240 i=sl.next;
00241 dst=ret;
00242 while(i) {
00243 foo=i;
00244 i=i->next;
00245 memcpy(dst, foo->s.s, foo->s.len);
00246 dst+=foo->s.len;
00247 pkg_free(foo);
00248 }
00249 *l=total_len;
00250 return ret;
00251
00252 error:
00253 i=sl.next;
00254 while(i) {
00255 foo=i;
00256 i=i->next;
00257 pkg_free(foo);
00258 }
00259 *l=0;
00260 return 0;
00261 }
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271 static inline void mi_print_routes( struct mi_node *node, dlg_t* dlg)
00272 {
00273 #define MI_ROUTE_PREFIX_S "Route: "
00274 #define MI_ROUTE_PREFIX_LEN (sizeof(MI_ROUTE_PREFIX_S)-1)
00275 #define MI_ROUTE_SEPARATOR_S ", "
00276 #define MI_ROUTE_SEPARATOR_LEN (sizeof(MI_ROUTE_SEPARATOR_S)-1)
00277 rr_t* ptr;
00278 int len;
00279 char *p, *s;
00280
00281 ptr = dlg->hooks.first_route;
00282
00283 if (ptr==NULL) {
00284 add_mi_node_child( node, 0, 0, 0, ".",1);
00285 return;
00286 }
00287
00288 len = MI_ROUTE_PREFIX_LEN;
00289 for( ; ptr ; ptr=ptr->next)
00290 len += ptr->len + MI_ROUTE_SEPARATOR_LEN*(ptr->next!=NULL);
00291 if (dlg->hooks.last_route)
00292 len += dlg->hooks.last_route->len + 2;
00293
00294
00295 s = pkg_malloc( len );
00296 if (s==0) {
00297 LM_ERR("no more pkg mem\n");
00298 return;
00299 }
00300
00301
00302 p = s;
00303 memcpy( p, MI_ROUTE_PREFIX_S, MI_ROUTE_PREFIX_LEN);
00304 p += MI_ROUTE_PREFIX_LEN;
00305
00306 for( ptr = dlg->hooks.first_route ; ptr ; ptr=ptr->next) {
00307 memcpy( p, ptr->nameaddr.name.s, ptr->len);
00308 p += ptr->len;
00309 if (ptr->next) {
00310 memcpy( p, MI_ROUTE_SEPARATOR_S, MI_ROUTE_SEPARATOR_LEN);
00311 p += MI_ROUTE_SEPARATOR_LEN;
00312 }
00313 }
00314
00315 if (dlg->hooks.last_route) {
00316 *(p++) = '<';
00317 memcpy( p, dlg->hooks.last_route->s, dlg->hooks.last_route->len);
00318 p += dlg->hooks.last_route->len;
00319 *(p++) = '>';
00320 }
00321
00322 add_mi_node_child( node, MI_DUP_VALUE, 0, 0, s, len);
00323 pkg_free(s);
00324 }
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335 static inline int mi_print_uris( struct mi_node *node, struct sip_msg* reply)
00336 {
00337 dlg_t* dlg;
00338
00339 if (reply==0)
00340 goto empty;
00341
00342 dlg = (dlg_t*)shm_malloc(sizeof(dlg_t));
00343 if (!dlg) {
00344 LM_ERR("no shm memory left\n");
00345 return -1;
00346 }
00347
00348 memset(dlg, 0, sizeof(dlg_t));
00349 if (dlg_response_uac(dlg, reply) < 0) {
00350 LM_ERR("failed to create dialog\n");
00351 free_dlg(dlg);
00352 return -1;
00353 }
00354
00355 if (dlg->state != DLG_CONFIRMED) {
00356 free_dlg(dlg);
00357 goto empty;
00358 }
00359
00360 if (dlg->hooks.request_uri->s) {
00361 add_mi_node_child( node, MI_DUP_VALUE, 0, 0,
00362 dlg->hooks.request_uri->s, dlg->hooks.request_uri->len);
00363 } else {
00364 add_mi_node_child( node, 0, 0, 0, ".",1);
00365 }
00366 if (dlg->hooks.next_hop->s) {
00367 add_mi_node_child( node, MI_DUP_VALUE, 0, 0,
00368 dlg->hooks.next_hop->s, dlg->hooks.next_hop->len);
00369 } else {
00370 add_mi_node_child( node, 0, 0, 0, ".",1);
00371 }
00372
00373 mi_print_routes( node, dlg);
00374
00375 free_dlg(dlg);
00376 return 0;
00377 empty:
00378 add_mi_node_child( node, 0, 0, 0, ".",1);
00379 add_mi_node_child( node, 0, 0, 0, ".",1);
00380 add_mi_node_child( node, 0, 0, 0, ".",1);
00381 return 0;
00382 }
00383
00384
00385 static void mi_uac_dlg_hdl( struct cell *t, int type, struct tmcb_params *ps )
00386 {
00387 struct mi_handler *mi_hdl;
00388 struct mi_root *rpl_tree;
00389 str text;
00390
00391 LM_DBG("MI UAC generated status %d\n", ps->code);
00392 if (!*ps->param)
00393 return;
00394
00395 mi_hdl = (struct mi_handler *)(*ps->param);
00396
00397 rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00398 if (rpl_tree==0)
00399 goto done;
00400
00401 if (ps->rpl==FAKED_REPLY) {
00402 get_reply_status( &text, ps->rpl, ps->code);
00403 if (text.s==0) {
00404 LM_ERR("get_reply_status failed\n");
00405 rpl_tree = 0;
00406 goto done;
00407 }
00408 add_mi_node_child( &rpl_tree->node, MI_DUP_VALUE, 0, 0,
00409 text.s, text.len);
00410 pkg_free(text.s);
00411 mi_print_uris( &rpl_tree->node, 0 );
00412 add_mi_node_child( &rpl_tree->node, 0, 0, 0, ".",1);
00413 } else {
00414 addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "%d %.*s",
00415 ps->rpl->first_line.u.reply.statuscode,
00416 ps->rpl->first_line.u.reply.reason.len,
00417 ps->rpl->first_line.u.reply.reason.s);
00418 mi_print_uris( &rpl_tree->node, ps->rpl);
00419 add_mi_node_child( &rpl_tree->node, MI_DUP_VALUE, 0, 0,
00420 ps->rpl->headers->name.s,
00421 ps->rpl->len-(ps->rpl->headers->name.s - ps->rpl->buf));
00422 }
00423
00424 LM_DBG("mi_callback successfully completed\n");
00425 done:
00426 if (ps->code >= 200) {
00427 mi_hdl->handler_f( rpl_tree, mi_hdl, 1 );
00428 *ps->param = 0;
00429 } else {
00430 mi_hdl->handler_f( rpl_tree, mi_hdl, 0 );
00431 }
00432 }
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448 struct mi_root* mi_tm_uac_dlg(struct mi_root* cmd_tree, void* param)
00449 {
00450 static char err_buf[MAX_REASON_LEN];
00451 static struct sip_msg tmp_msg;
00452 static dlg_t dlg;
00453 struct mi_root *rpl_tree;
00454 struct mi_node *node;
00455 struct sip_uri pruri;
00456 struct sip_uri pnexthop;
00457 struct socket_info* sock;
00458 str *method;
00459 str *ruri;
00460 str *nexthop;
00461 str *socket;
00462 str *hdrs;
00463 str *body;
00464 str s;
00465 str callid = {0,0};
00466 int sip_error;
00467 int proto;
00468 int port;
00469 int cseq;
00470 int n;
00471
00472 for( n=0,node = cmd_tree->node.kids; n<6 && node ; n++,node=node->next );
00473 if ( !(n==5 || n==6) || node!=0)
00474 return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00475
00476
00477 node = cmd_tree->node.kids;
00478 method = &node->value;
00479
00480
00481 node = node->next;
00482 ruri = &node->value;
00483 if (parse_uri( ruri->s, ruri->len, &pruri) < 0 )
00484 return init_mi_tree( 400, "Invalid RURI", 12);
00485
00486
00487 node = node->next;
00488 nexthop = &node->value;
00489 if (nexthop->len==1 && nexthop->s[0]=='.') {
00490 nexthop = 0;
00491 } else {
00492 if (parse_uri( nexthop->s, nexthop->len, &pnexthop) < 0 )
00493 return init_mi_tree( 400, "Invalid NEXTHOP", 15);
00494 }
00495
00496
00497 node = node->next;
00498 socket = &node->value;
00499 if (socket->len==1 && socket->s[0]=='.' ) {
00500 sock = 0;
00501 } else {
00502 if (parse_phostport( socket->s, socket->len, &s.s, &s.len,
00503 &port,&proto)!=0)
00504 return init_mi_tree( 404, "Invalid local socket", 20);
00505 sock = grep_sock_info( &s, (unsigned short)port, proto);
00506 if (sock==0)
00507 return init_mi_tree( 404, "Local socket not found", 22);
00508 }
00509
00510
00511 node = node->next;
00512 if (node->value.len==1 && node->value.s[0]=='.')
00513 hdrs = 0;
00514 else {
00515 hdrs = &node->value;
00516
00517 memset( &tmp_msg, 0, sizeof(struct sip_msg));
00518 tmp_msg.len = hdrs->len;
00519 tmp_msg.buf = tmp_msg.unparsed = hdrs->s;
00520 if (parse_headers( &tmp_msg, HDR_EOH_F, 0) == -1 )
00521 return init_mi_tree( 400, "Bad headers", 11);
00522 }
00523
00524
00525 node = node->next;
00526 if (node)
00527 body = &node->value;
00528 else
00529 body = 0;
00530
00531
00532
00533 rpl_tree = mi_check_msg( &tmp_msg, method, body, &cseq, &callid);
00534 if (rpl_tree) {
00535 if (tmp_msg.headers) free_hdr_field_lst(tmp_msg.headers);
00536 return rpl_tree;
00537 }
00538
00539 s.s = get_hfblock( nexthop ? nexthop : ruri,
00540 tmp_msg.headers, &s.len, &sock);
00541 if (s.s==0) {
00542 if (tmp_msg.headers) free_hdr_field_lst(tmp_msg.headers);
00543 return 0;
00544 }
00545
00546 memset( &dlg, 0, sizeof(dlg_t));
00547
00548
00549 if (callid.s && callid.len)
00550 dlg.id.call_id = callid;
00551 else
00552 generate_callid(&dlg.id.call_id);
00553
00554
00555
00556
00557
00558 if (!(get_from(&tmp_msg)->tag_value.len&&get_from(&tmp_msg)->tag_value.s))
00559 generate_fromtag(&dlg.id.loc_tag, &dlg.id.call_id);
00560
00561
00562 if (cseq!=-1)
00563 dlg.loc_seq.value = cseq;
00564 else
00565 dlg.loc_seq.value = DEFAULT_CSEQ;
00566 dlg.loc_seq.is_set = 1;
00567
00568 dlg.loc_uri = tmp_msg.from->body;
00569 dlg.rem_uri = tmp_msg.to->body;
00570 dlg.hooks.request_uri = ruri;
00571 dlg.hooks.next_hop = (nexthop ? nexthop : ruri);
00572 dlg.send_sock = sock;
00573
00574 if (cmd_tree->async_hdl==NULL)
00575 n = t_uac( method, &s, body, &dlg, 0, 0);
00576 else
00577 n = t_uac( method, &s, body, &dlg, mi_uac_dlg_hdl,
00578 (void*)cmd_tree->async_hdl);
00579
00580 pkg_free(s.s);
00581 if (tmp_msg.headers) free_hdr_field_lst(tmp_msg.headers);
00582
00583 if (n<=0) {
00584
00585 rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00586 if (rpl_tree==0)
00587 return 0;
00588
00589 n = err2reason_phrase( n, &sip_error, err_buf, sizeof(err_buf),
00590 "MI/UAC") ;
00591 if (n > 0 )
00592 addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "%d %.*s",
00593 sip_error, n, err_buf);
00594 else
00595 add_mi_node_child( &rpl_tree->node, 0, 0, 0,
00596 "500 MI/UAC failed", 17);
00597
00598 return rpl_tree;
00599 } else {
00600 if (cmd_tree->async_hdl==NULL)
00601 return init_mi_tree( 202, "Accepted", 8);
00602 else
00603 return MI_ROOT_ASYNC_RPL;
00604 }
00605 }
00606
00607
00608
00609
00610
00611
00612
00613 struct mi_root* mi_tm_cancel(struct mi_root* cmd_tree, void* param)
00614 {
00615 struct mi_node *node;
00616 struct cell *trans;
00617
00618 node = cmd_tree->node.kids;
00619 if ( !node || !node->next || node->next->next)
00620 return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00621
00622 if( t_lookup_callid( &trans, node->value, node->next->value) < 0 )
00623 return init_mi_tree( 481, "No such transaction", 19);
00624
00625
00626 LM_DBG("cancelling transaction %p\n",trans);
00627
00628 cancel_uacs( trans, ~0);
00629
00630 UNREF(trans);
00631
00632 return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00633 }
00634
00635
00636
00637
00638
00639
00640 struct mi_root* mi_tm_hash(struct mi_root* cmd_tree, void* param)
00641 {
00642 struct mi_root* rpl_tree= NULL;
00643 struct mi_node* rpl;
00644 struct mi_node* node;
00645 struct mi_attr* attr;
00646 struct s_table* tm_t;
00647 char *p;
00648 int i;
00649 int len;
00650
00651 rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00652 if (rpl_tree==0)
00653 return 0;
00654 rpl = &rpl_tree->node;
00655 tm_t = get_tm_table();
00656
00657 for (i=0; i<TM_TABLE_ENTRIES; i++) {
00658 p = int2str((unsigned long)i, &len );
00659 node = add_mi_node_child(rpl, MI_DUP_VALUE , 0, 0, p, len);
00660 if(node == NULL)
00661 goto error;
00662
00663 p = int2str((unsigned long)tm_t->entrys[i].cur_entries, &len );
00664 attr = add_mi_attr(node, MI_DUP_VALUE, "Current", 7, p, len );
00665 if(attr == NULL)
00666 goto error;
00667
00668 p = int2str((unsigned long)tm_t->entrys[i].acc_entries, &len );
00669 attr = add_mi_attr(node, MI_DUP_VALUE, "Total", 5, p, len );
00670 if(attr == NULL)
00671 goto error;
00672 }
00673
00674 return rpl_tree;
00675 error:
00676 free_mi_tree(rpl_tree);
00677 return init_mi_tree( 500, MI_INTERNAL_ERR_S, MI_INTERNAL_ERR_LEN);
00678 }
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690 struct mi_root* mi_tm_reply(struct mi_root* cmd_tree, void* param)
00691 {
00692 struct mi_node* node;
00693 unsigned int hash_index;
00694 unsigned int hash_label;
00695 unsigned int rpl_code;
00696 struct cell *trans;
00697 str *reason;
00698 str *totag;
00699 str *new_hdrs;
00700 str *body;
00701 str tmp;
00702 char *p;
00703 int n;
00704
00705 for( n=0,node = cmd_tree->node.kids; n<6 && node ; n++,node=node->next );
00706 if ( !(n==5 || n==6) || node!=0)
00707 return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00708
00709
00710
00711
00712 node = cmd_tree->node.kids;
00713 if (str2int( &node->value, &rpl_code)!=0 || rpl_code>=700)
00714 return init_mi_tree( 400, "Invalid reply code", 18);
00715
00716
00717 node = node->next;
00718 reason = &node->value;
00719
00720
00721 node = node->next;
00722 tmp = node->value;
00723 p = memchr( tmp.s, ':', tmp.len);
00724 if ( p==NULL)
00725 return init_mi_tree( 400, "Invalid trans_id", 16);
00726
00727 tmp.len = p-tmp.s;
00728 if( str2int( &tmp, &hash_index)!=0 )
00729 return init_mi_tree( 400, "Invalid index in trans_id", 25);
00730
00731 tmp.s = p+1;
00732 tmp.len = (node->value.s+node->value.len) - tmp.s;
00733 if( str2int( &tmp, &hash_label)!=0 )
00734 return init_mi_tree( 400, "Invalid label in trans_id", 25);
00735
00736 if( t_lookup_ident( &trans, hash_index, hash_label)<0 )
00737 return init_mi_tree( 404, "Transaction not found", 21);
00738
00739
00740 node = node->next;
00741 totag = &node->value;
00742
00743
00744 node = node->next;
00745 if (node->value.len==1 && node->value.s[0]=='.')
00746 new_hdrs = 0;
00747 else
00748 new_hdrs = &node->value;
00749
00750
00751 node = node->next;
00752 if (node)
00753 body = &node->value;
00754 else
00755 body = 0;
00756
00757
00758
00759 n = t_reply_with_body( trans, rpl_code, reason, body, new_hdrs, totag);
00760
00761 if (n<0)
00762 return init_mi_tree( 500, "Reply failed", 12);
00763
00764 return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00765 }
00766