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 "../../dprint.h"
00038 #include "../../ut.h"
00039 #include "../../qvalue.h"
00040 #include "../../ip_addr.h"
00041 #include "ul_mi.h"
00042 #include "dlist.h"
00043 #include "udomain.h"
00044 #include "utime.h"
00045 #include "p_usrloc_mod.h"
00046
00047
00049 #define MI_UL_CSEQ 1
00050
00051 static str mi_ul_cid = str_init("dfjrewr12386fd6-343@openser.mi");
00053 static str mi_ul_ua = str_init("Kamailio MI Server");
00054
00055 static str mi_ul_path = str_init("dummypath");
00056
00057
00058
00064 static inline udomain_t* mi_find_domain(str* table)
00065 {
00066
00067 LM_ERR("not available in sp-ul_db mode");
00068 return 0;
00069 }
00070
00071
00080 static inline int mi_fix_aor(str *aor)
00081 {
00082 char *p;
00083
00084 p = memchr( aor->s, '@', aor->len);
00085 if (use_domain) {
00086 if (p==NULL)
00087 return -1;
00088 } else {
00089 if (p)
00090 aor->len = p - aor->s;
00091 }
00092 strlower(aor);
00093
00094 return 0;
00095 }
00096
00097
00106 static inline int mi_add_aor_node(struct mi_node *parent, urecord_t* r, time_t t, int short_dump)
00107 {
00108 struct mi_node *anode, *cnode, *node;
00109 struct mi_attr *attr;
00110 ucontact_t* c;
00111 char *p;
00112 int len;
00113
00114 anode = add_mi_node_child( parent, MI_DUP_VALUE, "AOR", 3,
00115 r->aor.s, r->aor.len);
00116 if (anode==0)
00117 return -1;
00118
00119 if (short_dump)
00120 return 0;
00121
00122 for( c=r->contacts ; c ; c=c->next) {
00123
00124 cnode = add_mi_node_child( anode, MI_DUP_VALUE, "Contact", 7,
00125 c->c.s, c->c.len);
00126 if (cnode==0)
00127 return -1;
00128
00129
00130 if (c->expires == 0) {
00131 node = add_mi_node_child( cnode, 0, "Expires", 7, "permanent", 9);
00132 } else if (c->expires == UL_EXPIRED_TIME) {
00133 node = add_mi_node_child( cnode, 0, "Expires", 7, "deleted", 7);
00134 } else if (t > c->expires) {
00135 node = add_mi_node_child( cnode, 0, "Expires", 7, "expired", 7);
00136 } else {
00137 p = int2str((unsigned long)(c->expires - t), &len);
00138 node = add_mi_node_child( cnode, MI_DUP_VALUE, "Expires", 7,p,len);
00139 }
00140 if (node==0)
00141 return -1;
00142
00143
00144 p = q2str(c->q, (unsigned int*)&len);
00145 attr = add_mi_attr( cnode, MI_DUP_VALUE, "Q", 1, p, len);
00146 if (attr==0)
00147 return -1;
00148
00149
00150 node = add_mi_node_child( cnode, MI_DUP_VALUE, "Callid", 6,
00151 c->callid.s, c->callid.len);
00152 if (node==0)
00153 return -1;
00154
00155
00156 p = int2str((unsigned long)c->cseq, &len);
00157 node = add_mi_node_child( cnode, MI_DUP_VALUE, "Cseq", 4, p, len);
00158 if (node==0)
00159 return -1;
00160
00161
00162 if (c->user_agent.len) {
00163 node = add_mi_node_child( cnode, MI_DUP_VALUE, "User-agent", 10,
00164 c->user_agent.s, c->user_agent.len);
00165 if (node==0)
00166 return -1;
00167 }
00168
00169
00170 if (c->received.len) {
00171 node = add_mi_node_child( cnode, MI_DUP_VALUE, "Received", 8,
00172 c->received.s, c->received.len);
00173 if (node==0)
00174 return -1;
00175 }
00176
00177
00178 if (c->path.len) {
00179 node = add_mi_node_child( cnode, MI_DUP_VALUE, "Path", 4,
00180 c->path.s, c->path.len);
00181 if (node==0)
00182 return -1;
00183 }
00184
00185
00186 if (c->state == CS_NEW) {
00187 node = add_mi_node_child( cnode, 0, "State", 5, "CS_NEW", 6);
00188 } else if (c->state == CS_SYNC) {
00189 node = add_mi_node_child( cnode, 0, "State", 5, "CS_SYNC", 7);
00190 } else if (c->state== CS_DIRTY) {
00191 node = add_mi_node_child( cnode, 0, "State", 5, "CS_DIRTY", 8);
00192 } else {
00193 node = add_mi_node_child( cnode, 0, "State", 5, "CS_UNKNOWN", 10);
00194 }
00195 if (node==0)
00196 return -1;
00197
00198
00199 p = int2str((unsigned long)c->flags, &len);
00200 node = add_mi_node_child( cnode, MI_DUP_VALUE, "Flags", 5, p, len);
00201 if (node==0)
00202 return -1;
00203
00204
00205 p = int2str((unsigned long)c->cflags, &len);
00206 node = add_mi_node_child( cnode, MI_DUP_VALUE, "Cflags", 5, p, len);
00207 if (node==0)
00208 return -1;
00209
00210
00211 if (c->sock) {
00212 node = add_mi_node_child( cnode, 0, "Socket", 6,
00213 c->sock->sock_str.s, c->sock->sock_str.len);
00214 if (node==0)
00215 return -1;
00216 }
00217
00218
00219 p = int2str((unsigned long)c->methods, &len);
00220 node = add_mi_node_child( cnode, MI_DUP_VALUE, "Methods", 7, p, len);
00221 if (node==0)
00222 return -1;
00223
00224 }
00225
00226 return 0;
00227 }
00228
00229
00230
00231
00239 struct mi_root* mi_usrloc_rm_aor(struct mi_root *cmd, void *param)
00240 {
00241 struct mi_node *node;
00242 udomain_t *dom;
00243 str *aor;
00244
00245 node = cmd->node.kids;
00246 if (node==NULL || node->next==NULL || node->next->next!=NULL)
00247 return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00248
00249
00250 dom = mi_find_domain( &node->value );
00251 if (dom==NULL)
00252 return init_mi_tree( 404, "Table not found", 15);
00253
00254
00255 aor = &node->next->value;
00256 if ( mi_fix_aor(aor)!=0 )
00257 return init_mi_tree( 400, "Domain missing in AOR", 21);
00258
00259 lock_udomain( dom, aor);
00260 if (delete_urecord( dom, aor, 0) < 0) {
00261 unlock_udomain( dom, aor);
00262 return init_mi_tree( 500, "Failed to delete AOR", 20);
00263 }
00264
00265 unlock_udomain( dom, aor);
00266 return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00267 }
00268
00269
00277 struct mi_root* mi_usrloc_rm_contact(struct mi_root *cmd, void *param)
00278 {
00279 struct mi_node *node;
00280 udomain_t *dom;
00281 urecord_t *rec;
00282 ucontact_t* con;
00283 str *aor, *contact;
00284 int ret;
00285
00286 node = cmd->node.kids;
00287 if (node==NULL || node->next==NULL || node->next->next==NULL ||
00288 node->next->next->next!=NULL)
00289 return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00290
00291
00292 dom = mi_find_domain( &node->value );
00293 if (dom==NULL)
00294 return init_mi_tree( 404, "Table not found", 15);
00295
00296
00297 aor = &node->next->value;
00298 if ( mi_fix_aor(aor)!=0 )
00299 return init_mi_tree( 400, "Domain missing in AOR", 21);
00300
00301 lock_udomain( dom, aor);
00302
00303 ret = get_urecord( dom, aor, &rec);
00304 if (ret == 1) {
00305 unlock_udomain( dom, aor);
00306 return init_mi_tree( 404, "AOR not found", 13);
00307 }
00308
00309 contact = &node->next->next->value;
00310 ret = get_ucontact( rec, contact, &mi_ul_cid, &mi_ul_path, MI_UL_CSEQ+1, &con);
00311 if (ret < 0) {
00312 unlock_udomain( dom, aor);
00313 return 0;
00314 }
00315 if (ret > 0) {
00316 unlock_udomain( dom, aor);
00317 return init_mi_tree( 404, "Contact not found", 17);
00318 }
00319
00320 if (delete_ucontact(rec, con) < 0) {
00321 unlock_udomain( dom, aor);
00322 return 0;
00323 }
00324
00325 release_urecord(rec);
00326 unlock_udomain( dom, aor);
00327 return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00328 }
00329
00330
00337 struct mi_root* mi_usrloc_dump(struct mi_root *cmd, void *param)
00338 {
00339 LM_ERR("not available in sp-ul_db mode");
00340 return 0;
00341 }
00342
00343
00350 struct mi_root* mi_usrloc_flush(struct mi_root *cmd, void *param)
00351 {
00352 struct mi_root *rpl_tree;
00353
00354 rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00355 if (rpl_tree==NULL)
00356 return 0;
00357
00358 synchronize_all_udomains();
00359 return rpl_tree;
00360 }
00361
00362
00371 struct mi_root* mi_usrloc_add(struct mi_root *cmd, void *param)
00372 {
00373 ucontact_info_t ci;
00374 urecord_t* r;
00375 ucontact_t* c;
00376 struct mi_node *node;
00377 udomain_t *dom;
00378 str *aor, *contact;
00379 unsigned int ui_val;
00380 int n;
00381
00382 for( n=0,node = cmd->node.kids; n<9 && node ; n++,node=node->next );
00383 if (n!=9 || node!=0)
00384 return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00385
00386 node = cmd->node.kids;
00387
00388
00389 dom = mi_find_domain( &node->value );
00390 if (dom==NULL)
00391 return init_mi_tree( 404, "Table not found", 15);
00392
00393
00394 node = node->next;
00395 aor = &node->value;
00396 if ( mi_fix_aor(aor)!=0 )
00397 return init_mi_tree( 400, "Domain missing in AOR", 21);
00398
00399
00400 node = node->next;
00401 contact = &node->value;
00402
00403 memset( &ci, 0, sizeof(ucontact_info_t));
00404
00405
00406 node = node->next;
00407 if (str2int( &node->value, &ui_val) < 0)
00408 goto bad_syntax;
00409 ci.expires = ui_val;
00410
00411
00412 node = node->next;
00413 if (str2q( &ci.q, node->value.s, node->value.len) < 0)
00414 goto bad_syntax;
00415
00416
00417 node = node->next;
00418
00419
00420 node = node->next;
00421 if (str2int( &node->value, (unsigned int*)&ci.flags) < 0)
00422 goto bad_syntax;
00423
00424
00425 node = node->next;
00426 if (str2int( &node->value, (unsigned int*)&ci.cflags) < 0)
00427 goto bad_syntax;
00428
00429
00430 node = node->next;
00431 if (str2int( &node->value, (unsigned int*)&ci.methods) < 0)
00432 goto bad_syntax;
00433
00434 lock_udomain( dom, aor);
00435
00436 n = get_urecord( dom, aor, &r);
00437 if ( n==1) {
00438 if (insert_urecord( dom, aor, &r) < 0)
00439 goto lock_error;
00440 c = 0;
00441 } else {
00442 if (get_ucontact( r, contact, &mi_ul_cid, &mi_ul_path, MI_UL_CSEQ+1, &c) < 0)
00443 goto lock_error;
00444 }
00445
00446 get_act_time();
00447
00448 ci.callid = &mi_ul_cid;
00449 ci.user_agent = &mi_ul_ua;
00450 ci.cseq = MI_UL_CSEQ;
00451
00452 if (ci.expires!=0)
00453 ci.expires += act_time;
00454
00455 if (c) {
00456 if (update_ucontact( r, c, &ci) < 0)
00457 goto release_error;
00458 } else {
00459 if ( insert_ucontact( r, contact, &ci, &c) < 0 )
00460 goto release_error;
00461 }
00462
00463 release_urecord(r);
00464
00465 unlock_udomain( dom, aor);
00466
00467 return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00468 bad_syntax:
00469 return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
00470 release_error:
00471 release_urecord(r);
00472 lock_error:
00473 unlock_udomain( dom, aor);
00474 return init_mi_tree( 500, MI_INTERNAL_ERR_S, MI_INTERNAL_ERR_LEN);
00475 }
00476
00477
00485 struct mi_root* mi_usrloc_show_contact(struct mi_root *cmd, void *param)
00486 {
00487 struct mi_root *rpl_tree;
00488 struct mi_node *rpl, *node;
00489 udomain_t *dom;
00490 urecord_t *rec;
00491 ucontact_t* con;
00492 str *aor;
00493 int ret;
00494
00495 node = cmd->node.kids;
00496 if (node==NULL || node->next==NULL || node->next->next!=NULL)
00497 return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00498
00499
00500 dom = mi_find_domain( &node->value );
00501 if (dom==NULL)
00502 return init_mi_tree( 404, "Table not found", 15);
00503
00504
00505 aor = &node->next->value;
00506 if ( mi_fix_aor(aor)!=0 )
00507 return init_mi_tree( 400, "Domain missing in AOR", 21);
00508
00509 lock_udomain( dom, aor);
00510
00511 ret = get_urecord( dom, aor, &rec);
00512 if (ret == 1) {
00513 unlock_udomain( dom, aor);
00514 return init_mi_tree( 404, "AOR not found", 13);
00515 }
00516
00517 get_act_time();
00518 rpl_tree = 0;
00519 rpl = 0;
00520
00521 for( con=rec->contacts ; con ; con=con->next) {
00522 if (VALID_CONTACT( con, act_time)) {
00523 if (rpl_tree==0) {
00524 rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00525 if (rpl_tree==0)
00526 goto error;
00527 rpl = &rpl_tree->node;
00528 }
00529
00530 node = addf_mi_node_child( rpl, 0, "Contact", 7,
00531 "<%.*s>;q=%s;expires=%d;flags=0x%X;cflags=0x%X;socket=<%.*s>;"
00532 "methods=0x%X"
00533 "%s%.*s%s"
00534 "%s%.*s%s"
00535 "%s%.*s%s",
00536 con->c.len, ZSW(con->c.s),
00537 q2str(con->q, 0), (int)(con->expires - act_time),
00538 con->flags, con->cflags,
00539 con->sock?con->sock->sock_str.len:3,
00540 con->sock?con->sock->sock_str.s:"NULL",
00541 con->methods,
00542 con->received.len?";received=<":"",con->received.len,
00543 ZSW(con->received.s), con->received.len?">":"",
00544 con->user_agent.len?";user_agent=<":"",con->user_agent.len,
00545 ZSW(con->user_agent.s), con->user_agent.len?">":"",
00546 con->path.len?";path=<":"", con->path.len,
00547 ZSW(con->path.s), con->path.len?">":""
00548 );
00549 if (node==0)
00550 goto error;
00551 }
00552 }
00553
00554 unlock_udomain( dom, aor);
00555
00556 if (rpl_tree==0)
00557 return init_mi_tree( 404 , "AOR has no contacts", 18);
00558
00559 return rpl_tree;
00560 error:
00561 if (rpl_tree)
00562 free_mi_tree( rpl_tree );
00563 unlock_udomain( dom, aor);
00564 return 0;
00565 }