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