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
00035 #include <string.h>
00036 #include <stdio.h>
00037 #include "../../lib/kmi/mi.h"
00038 #include "../../lib/srutils/sruid.h"
00039 #include "../../dprint.h"
00040 #include "../../ut.h"
00041 #include "../../qvalue.h"
00042 #include "../../ip_addr.h"
00043 #include "ul_mi.h"
00044 #include "dlist.h"
00045 #include "udomain.h"
00046 #include "utime.h"
00047 #include "ul_mod.h"
00048 #include "usrloc.h"
00049
00051 #define MI_UL_CSEQ 1
00052
00053 static str mi_ul_cid = str_init("dfjrewr12386fd6-343@kamailio.mi");
00055 static str mi_ul_ua = str_init("SIP Router MI Server");
00057 static str mi_ul_path = str_init("dummypath");
00058
00059 extern sruid_t _ul_sruid;
00060
00061
00062
00068 static inline udomain_t* mi_find_domain(str* table)
00069 {
00070 dlist_t* dom;
00071
00072 for( dom=root ; dom ; dom=dom->next ) {
00073 if ((dom->name.len == table->len) &&
00074 !memcmp(dom->name.s, table->s, table->len))
00075 return dom->d;
00076 }
00077 return 0;
00078 }
00079
00080
00089 static inline int mi_fix_aor(str *aor)
00090 {
00091 char *p;
00092
00093 p = memchr( aor->s, '@', aor->len);
00094 if (use_domain) {
00095 if (p==NULL)
00096 return -1;
00097 } else {
00098 if (p)
00099 aor->len = p - aor->s;
00100 }
00101 strlower(aor);
00102
00103 return 0;
00104 }
00105
00106
00115 static inline int mi_add_aor_node(struct mi_node *parent, urecord_t* r, time_t t, int short_dump)
00116 {
00117 struct mi_node *anode, *cnode, *node;
00118 struct mi_attr *attr;
00119 ucontact_t* c;
00120 char *p;
00121 int len;
00122
00123 anode = add_mi_node_child( parent, MI_DUP_VALUE, "AOR", 3,
00124 r->aor.s, r->aor.len);
00125 if (anode==0)
00126 return -1;
00127
00128 if (short_dump)
00129 return 0;
00130
00131 #if 0
00132
00133 p = int2str((unsigned long)r->aorhash, &len);
00134 node = add_mi_node_child( anode, MI_DUP_VALUE, "HashID", 6, p, len);
00135 if (node==0)
00136 return -1;
00137 #endif
00138
00139 for( c=r->contacts ; c ; c=c->next) {
00140
00141 cnode = add_mi_node_child( anode, MI_DUP_VALUE, "Contact", 7,
00142 c->c.s, c->c.len);
00143 if (cnode==0)
00144 return -1;
00145
00146
00147 if (c->expires == 0) {
00148 node = add_mi_node_child( cnode, 0, "Expires", 7, "permanent", 9);
00149 } else if (c->expires == UL_EXPIRED_TIME) {
00150 node = add_mi_node_child( cnode, 0, "Expires", 7, "deleted", 7);
00151 } else if (t > c->expires) {
00152 node = add_mi_node_child( cnode, 0, "Expires", 7, "expired", 7);
00153 } else {
00154 p = int2str((unsigned long)(c->expires - t), &len);
00155 node = add_mi_node_child( cnode, MI_DUP_VALUE, "Expires", 7,p,len);
00156 }
00157 if (node==0)
00158 return -1;
00159
00160
00161 p = q2str(c->q, (unsigned int*)&len);
00162 attr = add_mi_attr( cnode, MI_DUP_VALUE, "Q", 1, p, len);
00163 if (attr==0)
00164 return -1;
00165
00166
00167 node = add_mi_node_child( cnode, MI_DUP_VALUE, "Callid", 6,
00168 c->callid.s, c->callid.len);
00169 if (node==0)
00170 return -1;
00171
00172
00173 p = int2str((unsigned long)c->cseq, &len);
00174 node = add_mi_node_child( cnode, MI_DUP_VALUE, "Cseq", 4, p, len);
00175 if (node==0)
00176 return -1;
00177
00178
00179 if (c->user_agent.len) {
00180 node = add_mi_node_child( cnode, MI_DUP_VALUE, "User-agent", 10,
00181 c->user_agent.s, c->user_agent.len);
00182 if (node==0)
00183 return -1;
00184 }
00185
00186
00187 if (c->received.len) {
00188 node = add_mi_node_child( cnode, MI_DUP_VALUE, "Received", 8,
00189 c->received.s, c->received.len);
00190 if (node==0)
00191 return -1;
00192 }
00193
00194
00195 if (c->path.len) {
00196 node = add_mi_node_child( cnode, MI_DUP_VALUE, "Path", 4,
00197 c->path.s, c->path.len);
00198 if (node==0)
00199 return -1;
00200 }
00201
00202
00203 if (c->state == CS_NEW) {
00204 node = add_mi_node_child( cnode, 0, "State", 5, "CS_NEW", 6);
00205 } else if (c->state == CS_SYNC) {
00206 node = add_mi_node_child( cnode, 0, "State", 5, "CS_SYNC", 7);
00207 } else if (c->state== CS_DIRTY) {
00208 node = add_mi_node_child( cnode, 0, "State", 5, "CS_DIRTY", 8);
00209 } else {
00210 node = add_mi_node_child( cnode, 0, "State", 5, "CS_UNKNOWN", 10);
00211 }
00212 if (node==0)
00213 return -1;
00214
00215
00216 p = int2str((unsigned long)c->flags, &len);
00217 node = add_mi_node_child( cnode, MI_DUP_VALUE, "Flags", 5, p, len);
00218 if (node==0)
00219 return -1;
00220
00221
00222 p = int2str((unsigned long)c->cflags, &len);
00223 node = add_mi_node_child( cnode, MI_DUP_VALUE, "Cflags", 5, p, len);
00224 if (node==0)
00225 return -1;
00226
00227
00228 if (c->sock) {
00229 node = add_mi_node_child( cnode, 0, "Socket", 6,
00230 c->sock->sock_str.s, c->sock->sock_str.len);
00231 if (node==0)
00232 return -1;
00233 }
00234
00235
00236 p = int2str((unsigned long)c->methods, &len);
00237 node = add_mi_node_child( cnode, MI_DUP_VALUE, "Methods", 7, p, len);
00238 if (node==0)
00239 return -1;
00240
00241
00242 if (c->ruid.len) {
00243 node = add_mi_node_child( cnode, MI_DUP_VALUE, "Ruid", 4,
00244 c->ruid.s, c->ruid.len);
00245 if (node==0)
00246 return -1;
00247 }
00248
00249
00250 if (c->instance.len) {
00251 node = add_mi_node_child( cnode, MI_DUP_VALUE, "Instance", 8,
00252 c->instance.s, c->instance.len);
00253 if (node==0)
00254 return -1;
00255 }
00256
00257
00258 p = int2str((unsigned long)c->reg_id, &len);
00259 node = add_mi_node_child( cnode, MI_DUP_VALUE, "Reg-Id", 6, p, len);
00260 if (node==0)
00261 return -1;
00262 }
00263
00264 return 0;
00265 }
00266
00267
00268
00269
00277 struct mi_root* mi_usrloc_rm_aor(struct mi_root *cmd, void *param)
00278 {
00279 struct mi_node *node;
00280 udomain_t *dom;
00281 str *aor;
00282
00283 node = cmd->node.kids;
00284 if (node==NULL || node->next==NULL || node->next->next!=NULL)
00285 return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00286
00287
00288 dom = mi_find_domain( &node->value );
00289 if (dom==NULL)
00290 return init_mi_tree( 404, "Table not found", 15);
00291
00292
00293 aor = &node->next->value;
00294 if ( mi_fix_aor(aor)!=0 )
00295 return init_mi_tree( 400, "Domain missing in AOR", 21);
00296
00297 lock_udomain( dom, aor);
00298 if (delete_urecord( dom, aor, 0) < 0) {
00299 unlock_udomain( dom, aor);
00300 return init_mi_tree( 500, "Failed to delete AOR", 20);
00301 }
00302
00303 unlock_udomain( dom, aor);
00304 return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00305 }
00306
00307
00315 struct mi_root* mi_usrloc_rm_contact(struct mi_root *cmd, void *param)
00316 {
00317 struct mi_node *node;
00318 udomain_t *dom;
00319 urecord_t *rec;
00320 ucontact_t* con;
00321 str *aor, *contact;
00322 int ret;
00323
00324 node = cmd->node.kids;
00325 if (node==NULL || node->next==NULL || node->next->next==NULL ||
00326 node->next->next->next!=NULL)
00327 return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00328
00329
00330 dom = mi_find_domain( &node->value );
00331 if (dom==NULL)
00332 return init_mi_tree( 404, "Table not found", 15);
00333
00334
00335 aor = &node->next->value;
00336 if ( mi_fix_aor(aor)!=0 )
00337 return init_mi_tree( 400, "Domain missing in AOR", 21);
00338
00339 lock_udomain( dom, aor);
00340
00341 ret = get_urecord( dom, aor, &rec);
00342 if (ret == 1) {
00343 unlock_udomain( dom, aor);
00344 return init_mi_tree( 404, "AOR not found", 13);
00345 }
00346
00347 contact = &node->next->next->value;
00348 ret = get_ucontact( rec, contact, &mi_ul_cid, &mi_ul_path, MI_UL_CSEQ+1, &con);
00349 if (ret < 0) {
00350 unlock_udomain( dom, aor);
00351 return 0;
00352 }
00353 if (ret > 0) {
00354 unlock_udomain( dom, aor);
00355 return init_mi_tree( 404, "Contact not found", 17);
00356 }
00357
00358 if (delete_ucontact(rec, con) < 0) {
00359 unlock_udomain( dom, aor);
00360 return 0;
00361 }
00362
00363 release_urecord(rec);
00364 unlock_udomain( dom, aor);
00365 return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00366 }
00367
00368
00375 struct mi_root* mi_usrloc_dump(struct mi_root *cmd, void *param)
00376 {
00377 struct mi_root *rpl_tree;
00378 struct mi_node *rpl, *node;
00379 struct mi_attr *attr;
00380 struct urecord* r;
00381 dlist_t* dl;
00382 udomain_t* dom;
00383 time_t t;
00384 char *p;
00385 int max, len, n, i, short_dump;
00386
00387 node = cmd->node.kids;
00388 if (node && node->next)
00389 return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00390
00391 if (node && node->value.len==5 && !strncasecmp(node->value.s, "brief", 5)){
00392
00393 short_dump = 1;
00394 } else {
00395 short_dump = 0;
00396 }
00397
00398 rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00399 if (rpl_tree==NULL)
00400 return 0;
00401 rpl = &rpl_tree->node;
00402 t = time(0);
00403
00404 for( dl=root ; dl ; dl=dl->next ) {
00405
00406 node = add_mi_node_child( rpl, 0, "Domain", 6,
00407 dl->name.s, dl->name.len);
00408 if (node==0)
00409 goto error;
00410
00411 dom = dl->d;
00412
00413 p= int2str((unsigned long)dom->size, &len);
00414 attr = add_mi_attr( node, MI_DUP_VALUE, "table", 5, p, len);
00415 if (attr==0)
00416 goto error;
00417
00418
00419 for(i=0,n=0,max=0; i<dom->size; i++) {
00420 lock_ulslot( dom, i);
00421
00422 n += dom->table[i].n;
00423 if(max<dom->table[i].n)
00424 max= dom->table[i].n;
00425 for( r = dom->table[i].first ; r ; r=r->next ) {
00426
00427 if (mi_add_aor_node( node, r, t, short_dump)!=0) {
00428 unlock_ulslot( dom, i);
00429 goto error;
00430 }
00431 }
00432
00433 unlock_ulslot( dom, i);
00434 }
00435
00436
00437 p= int2str((unsigned long)n, &len);
00438 attr = add_mi_attr( node, MI_DUP_VALUE, "records", 7, p, len);
00439 if (attr==0)
00440 goto error;
00441
00442 p= int2str((unsigned long)max, &len);
00443 attr = add_mi_attr( node, MI_DUP_VALUE, "max_slot", 8, p, len);
00444 if (attr==0)
00445 goto error;
00446
00447 }
00448
00449 return rpl_tree;
00450 error:
00451 free_mi_tree(rpl_tree);
00452 return 0;
00453 }
00454
00455
00462 struct mi_root* mi_usrloc_flush(struct mi_root *cmd, void *param)
00463 {
00464 struct mi_root *rpl_tree;
00465
00466 rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00467 if (rpl_tree==NULL)
00468 return 0;
00469
00470 synchronize_all_udomains(0, 1);
00471 return rpl_tree;
00472 }
00473
00474
00483 struct mi_root* mi_usrloc_add(struct mi_root *cmd, void *param)
00484 {
00485 ucontact_info_t ci;
00486 urecord_t* r;
00487 ucontact_t* c;
00488 struct mi_node *node;
00489 udomain_t *dom;
00490 str *aor, *contact;
00491 unsigned int ui_val;
00492 int n;
00493
00494 for( n=0,node = cmd->node.kids; n<9 && node ; n++,node=node->next );
00495 if (n!=9 || node!=0)
00496 return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00497
00498 node = cmd->node.kids;
00499
00500
00501 dom = mi_find_domain( &node->value );
00502 if (dom==NULL)
00503 return init_mi_tree( 404, "Table not found", 15);
00504
00505
00506 node = node->next;
00507 aor = &node->value;
00508 if ( mi_fix_aor(aor)!=0 )
00509 return init_mi_tree( 400, "Domain missing in AOR", 21);
00510
00511
00512 node = node->next;
00513 contact = &node->value;
00514
00515 memset( &ci, 0, sizeof(ucontact_info_t));
00516
00517
00518 node = node->next;
00519 if (str2int( &node->value, &ui_val) < 0)
00520 goto bad_syntax;
00521 ci.expires = ui_val;
00522
00523
00524 node = node->next;
00525 if (str2q( &ci.q, node->value.s, node->value.len) < 0)
00526 goto bad_syntax;
00527
00528
00529 node = node->next;
00530
00531
00532 node = node->next;
00533 if (str2int( &node->value, (unsigned int*)&ci.flags) < 0)
00534 goto bad_syntax;
00535
00536
00537 node = node->next;
00538 if (str2int( &node->value, (unsigned int*)&ci.cflags) < 0)
00539 goto bad_syntax;
00540
00541
00542 node = node->next;
00543 if (str2int( &node->value, (unsigned int*)&ci.methods) < 0)
00544 goto bad_syntax;
00545
00546 if(sruid_next(&_ul_sruid)<0)
00547 goto error;
00548 ci.ruid = _ul_sruid.uid;
00549
00550 lock_udomain( dom, aor);
00551
00552 n = get_urecord( dom, aor, &r);
00553 if ( n==1) {
00554 if (insert_urecord( dom, aor, &r) < 0)
00555 goto lock_error;
00556 c = 0;
00557 } else {
00558 if (get_ucontact( r, contact, &mi_ul_cid, &mi_ul_path, MI_UL_CSEQ+1, &c) < 0)
00559 goto lock_error;
00560 }
00561
00562 get_act_time();
00563
00564 ci.callid = &mi_ul_cid;
00565 ci.user_agent = &mi_ul_ua;
00566 ci.cseq = MI_UL_CSEQ;
00567
00568 if (ci.expires!=0)
00569 ci.expires += act_time;
00570
00571 if (c) {
00572 if (update_ucontact( r, c, &ci) < 0)
00573 goto release_error;
00574 } else {
00575 if ( insert_ucontact( r, contact, &ci, &c) < 0 )
00576 goto release_error;
00577 }
00578
00579 release_urecord(r);
00580
00581 unlock_udomain( dom, aor);
00582
00583 return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00584 bad_syntax:
00585 return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
00586 release_error:
00587 release_urecord(r);
00588 lock_error:
00589 unlock_udomain( dom, aor);
00590 error:
00591 return init_mi_tree( 500, MI_INTERNAL_ERR_S, MI_INTERNAL_ERR_LEN);
00592 }
00593
00594
00602 struct mi_root* mi_usrloc_show_contact(struct mi_root *cmd, void *param)
00603 {
00604 struct mi_root *rpl_tree;
00605 struct mi_node *rpl, *node;
00606 udomain_t *dom;
00607 urecord_t *rec;
00608 ucontact_t* con;
00609 str *aor;
00610 int ret;
00611
00612 node = cmd->node.kids;
00613 if (node==NULL || node->next==NULL || node->next->next!=NULL)
00614 return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00615
00616
00617 dom = mi_find_domain( &node->value );
00618 if (dom==NULL)
00619 return init_mi_tree( 404, "Table not found", 15);
00620
00621
00622 aor = &node->next->value;
00623 if ( mi_fix_aor(aor)!=0 )
00624 return init_mi_tree( 400, "Domain missing in AOR", 21);
00625
00626 lock_udomain( dom, aor);
00627
00628 ret = get_urecord( dom, aor, &rec);
00629 if (ret == 1) {
00630 unlock_udomain( dom, aor);
00631 return init_mi_tree( 404, "AOR not found", 13);
00632 }
00633
00634 get_act_time();
00635 rpl_tree = 0;
00636 rpl = 0;
00637
00638 for( con=rec->contacts ; con ; con=con->next) {
00639 if (VALID_CONTACT( con, act_time)) {
00640 if (rpl_tree==0) {
00641 rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00642 if (rpl_tree==0)
00643 goto error;
00644 rpl = &rpl_tree->node;
00645 }
00646
00647 node = addf_mi_node_child( rpl, 0, "Contact", 7,
00648 "<%.*s>;q=%s;expires=%d;flags=0x%X;cflags=0x%X;socket=<%.*s>;"
00649 "methods=0x%X"
00650 "%s%.*s%s"
00651 "%s%.*s%s"
00652 "%s%.*s%s",
00653 con->c.len, ZSW(con->c.s),
00654 q2str(con->q, 0), (int)(con->expires - act_time),
00655 con->flags, con->cflags,
00656 con->sock?con->sock->sock_str.len:3,
00657 con->sock?con->sock->sock_str.s:"NULL",
00658 con->methods,
00659 con->received.len?";received=<":"",con->received.len,
00660 ZSW(con->received.s), con->received.len?">":"",
00661 con->user_agent.len?";user_agent=<":"",con->user_agent.len,
00662 ZSW(con->user_agent.s), con->user_agent.len?">":"",
00663 con->path.len?";path=<":"", con->path.len,
00664 ZSW(con->path.s), con->path.len?">":""
00665 );
00666 if (node==0)
00667 goto error;
00668 }
00669 }
00670
00671 unlock_udomain( dom, aor);
00672
00673 if (rpl_tree==0)
00674 return init_mi_tree( 404 , "AOR has no contacts", 18);
00675
00676 return rpl_tree;
00677 error:
00678 if (rpl_tree)
00679 free_mi_tree( rpl_tree );
00680 unlock_udomain( dom, aor);
00681 return 0;
00682 }