00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00027 #include "../../sr_module.h"
00028 #include "../../mem/mem.h"
00029 #include "../../mem/shm_mem.h"
00030 #include "../../lib/kmi/mi.h"
00031 #include <sys/time.h>
00032 #include <poll.h>
00033 #include <stdlib.h>
00034 #include <unistd.h>
00035 #include <ctype.h>
00036 #include <sys/socket.h>
00037 #include <netinet/in.h>
00038 #include <arpa/inet.h>
00039 #include <errno.h>
00040
00041 MODULE_VERSION
00042
00043
00044 #define NETBUFSIZE 200
00045
00046
00047 static char* modp_server = NULL;
00048 static int timeout = 50;
00049 static int timeoutlogs = -10;
00050 static int *active = NULL;
00051
00052
00057 struct multiparam_t {
00058 enum {
00059 MP_INT,
00060 MP_STR,
00061 MP_AVP,
00062 MP_PVE,
00063 } type;
00064 union {
00065 int n;
00066 str s;
00067 struct {
00068 unsigned short flags;
00069 int_str name;
00070 } a;
00071 pv_elem_t *p;
00072 } u;
00073 };
00074
00075
00076
00077 static int pdb_query(struct sip_msg *_msg, struct multiparam_t *_number, struct multiparam_t *_dstavp);
00078
00079
00080 static int pdb_query_fixup(void **arg, int arg_no);
00081
00082
00083 static int mod_init(void);
00084 static int child_init(int rank);
00085 static int mi_child_init(void);
00086 static void mod_destroy();
00087
00088
00089 struct mi_root * mi_pdb_status(struct mi_root* cmd, void* param);
00090 struct mi_root * mi_pdb_activate(struct mi_root* cmd, void* param);
00091 struct mi_root * mi_pdb_deactivate(struct mi_root* cmd, void* param);
00092
00093
00094 static cmd_export_t cmds[]={
00095 { "pdb_query", (cmd_function)pdb_query, 2, pdb_query_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE },
00096 {0,0,0,0,0,0}
00097 };
00098
00099
00100 static param_export_t params[] = {
00101 {"server", STR_PARAM, &modp_server },
00102 {"timeout", INT_PARAM, &timeout },
00103 {0, 0, 0 }
00104 };
00105
00106
00107
00108 static mi_export_t mi_cmds[] = {
00109 { "pdb_status", mi_pdb_status, MI_NO_INPUT_FLAG, 0, mi_child_init },
00110 { "pdb_activate", mi_pdb_activate, MI_NO_INPUT_FLAG, 0, mi_child_init },
00111 { "pdb_deactivate", mi_pdb_deactivate, MI_NO_INPUT_FLAG, 0, mi_child_init },
00112 { 0, 0, 0, 0, 0}
00113 };
00114
00115
00116 struct module_exports exports = {
00117 "pdb",
00118 DEFAULT_DLFLAGS,
00119 cmds,
00120 params,
00121 0,
00122 mi_cmds,
00123 0,
00124 0,
00125 mod_init,
00126 0,
00127 mod_destroy,
00128 child_init
00129 };
00130
00131
00132 struct server_item_t {
00133 struct server_item_t *next;
00134 char *host;
00135 unsigned short int port;
00136 struct sockaddr_in dstaddr;
00137 socklen_t dstaddrlen;
00138 int sock;
00139 };
00140
00141
00142 struct server_list_t {
00143 struct server_item_t *head;
00144 int nserver;
00145 struct pollfd *fds;
00146 };
00147
00148
00150 static struct server_list_t *server_list;
00151
00152
00157 static int pdb_query(struct sip_msg *_msg, struct multiparam_t *_number, struct multiparam_t *_dstavp)
00158 {
00159 struct timeval tstart, tnow;
00160 struct server_item_t *server;
00161 short int carrierid;
00162 char buf[NETBUFSIZE+1+sizeof(carrierid)];
00163 size_t reqlen;
00164 int_str avp_val;
00165 struct usr_avp *avp;
00166 int i, ret, nflush;
00167 long int td;
00168 str number = { .len = 0, .s = NULL};
00169
00170 if ((active == NULL) || (*active == 0)) return -1;
00171
00172 switch (_number->type) {
00173 case MP_STR:
00174 number = _number->u.s;
00175 break;
00176 case MP_AVP:
00177 avp = search_first_avp(_number->u.a.flags, _number->u.a.name, &avp_val, 0);
00178 if (!avp) {
00179 LM_ERR("cannot find AVP '%.*s'\n", _number->u.a.name.s.len, _number->u.a.name.s.s);
00180 return -1;
00181 }
00182 if ((avp->flags&AVP_VAL_STR)==0) {
00183 LM_ERR("cannot process integer value in AVP '%.*s'\n", _number->u.a.name.s.len, _number->u.a.name.s.s);
00184 return -1;
00185 }
00186 else number = avp_val.s;
00187 break;
00188 case MP_PVE:
00189 if (pv_printf_s(_msg, _number->u.p, &number)<0) {
00190 LM_ERR("cannot print the number\n");
00191 return -1;
00192 }
00193 break;
00194 default:
00195 LM_ERR("invalid number type\n");
00196 return -1;
00197 }
00198
00199 LM_DBG("querying '%.*s'...\n", number.len, number.s);
00200 if (server_list == NULL) return -1;
00201 if (server_list->fds == NULL) return -1;
00202
00203 if (gettimeofday(&tstart, NULL) != 0) {
00204 LM_ERR("gettimeofday() failed with errno=%d (%s)\n", errno, strerror(errno));
00205 return -1;
00206 }
00207
00208
00209 server = server_list->head;
00210 while (server) {
00211 nflush = 0;
00212 while (recv(server->sock, buf, NETBUFSIZE, MSG_DONTWAIT) > 0) {
00213 nflush++;
00214 if (gettimeofday(&tnow, NULL) != 0) {
00215 LM_ERR("gettimeofday() failed with errno=%d (%s)\n", errno, strerror(errno));
00216 return -1;
00217 }
00218 td=(tnow.tv_usec-tstart.tv_usec+(tnow.tv_sec-tstart.tv_sec)*1000000) / 1000;
00219 if (td > timeout) {
00220 LM_WARN("exceeded timeout while flushing recv buffer.\n");
00221 return -1;
00222 }
00223 }
00224 LM_DBG("flushed %d packets for '%s:%d'\n", nflush, server->host, server->port);
00225 server = server ->next;
00226 }
00227
00228
00229 reqlen = number.len + 1;
00230 if (reqlen > NETBUFSIZE) {
00231 LM_ERR("number too long '%.*s'.\n", number.len, number.s);
00232 return -1;
00233 }
00234 strncpy(buf, number.s, number.len);
00235 buf[number.len] = '\0';
00236
00237
00238 server = server_list->head;
00239 while (server) {
00240 LM_DBG("sending request to '%s:%d'\n", server->host, server->port);
00241 ret=sendto(server->sock, buf, reqlen, MSG_DONTWAIT, (struct sockaddr *)&(server->dstaddr), server->dstaddrlen);
00242 if (ret < 0) {
00243 LM_ERR("sendto() failed with errno=%d (%s)\n", errno, strerror(errno));
00244 }
00245 server = server->next;
00246 }
00247
00248
00249 for (;;) {
00250 if (gettimeofday(&tnow, NULL) != 0) {
00251 LM_ERR("gettimeofday() failed with errno=%d (%s)\n", errno, strerror(errno));
00252 return -1;
00253 }
00254 td=(tnow.tv_usec-tstart.tv_usec+(tnow.tv_sec-tstart.tv_sec)*1000000) / 1000;
00255 if (td > timeout) {
00256 timeoutlogs++;
00257 if (timeoutlogs<0) {
00258 LM_WARN("exceeded timeout while waiting for response.\n");
00259 }
00260 else if (timeoutlogs>1000) {
00261 LM_WARN("exceeded timeout %d times while waiting for response.\n", timeoutlogs);
00262 timeoutlogs=0;
00263 }
00264 return -1;
00265 }
00266
00267 ret=poll(server_list->fds, server_list->nserver, timeout-td);
00268 for (i=0; i<server_list->nserver; i++) {
00269 if (server_list->fds[i].revents & POLLIN) {
00270 if (recv(server_list->fds[i].fd, buf, NETBUFSIZE, MSG_DONTWAIT) > 0) {
00271 buf[NETBUFSIZE] = '\0';
00272 if (strncmp(buf, number.s, number.len) == 0) {
00273 carrierid=ntohs(*((short int *)&(buf[reqlen])));
00274 goto found;
00275 }
00276 }
00277 }
00278 server_list->fds[i].revents = 0;
00279 }
00280 }
00281
00282 found:
00283 if (timeoutlogs>0) {
00284 LM_WARN("exceeded timeout while waiting for response (buffered %d lines).\n", timeoutlogs);
00285 timeoutlogs=-10;
00286 }
00287 if (gettimeofday(&tnow, NULL) == 0) {
00288 LM_INFO("got an answer in %f ms\n", ((double)(tnow.tv_usec-tstart.tv_usec+(tnow.tv_sec-tstart.tv_sec)*1000000))/1000);
00289 }
00290 avp_val.n=carrierid;
00291
00292 if (add_avp(_dstavp->u.a.flags, _dstavp->u.a.name, avp_val)<0) {
00293 LM_ERR("add AVP failed\n");
00294 return -1;
00295 }
00296
00297 return 1;
00298 }
00299
00300
00308 static int mp_fixup(void ** param) {
00309 pv_spec_t avp_spec;
00310 struct multiparam_t *mp;
00311 str s;
00312
00313 mp = (struct multiparam_t *)pkg_malloc(sizeof(struct multiparam_t));
00314 if (mp == NULL) {
00315 PKG_MEM_ERROR;
00316 return -1;
00317 }
00318 memset(mp, 0, sizeof(struct multiparam_t));
00319
00320 s.s = (char *)(*param);
00321 s.len = strlen(s.s);
00322
00323 if (s.s[0]!='$') {
00324
00325 mp->type=MP_STR;
00326 mp->u.s=s;
00327 }
00328 else {
00329
00330 if (pv_parse_spec(&s, &avp_spec)==0) {
00331 LM_ERR("pv_parse_spec failed for '%s'\n", (char *)(*param));
00332 pkg_free(mp);
00333 return -1;
00334 }
00335 if (avp_spec.type==PVT_AVP) {
00336
00337 mp->type=MP_AVP;
00338 if(pv_get_avp_name(0, &(avp_spec.pvp), &(mp->u.a.name), &(mp->u.a.flags))!=0) {
00339 LM_ERR("Invalid AVP definition <%s>\n", (char *)(*param));
00340 pkg_free(mp);
00341 return -1;
00342 }
00343 } else {
00344 mp->type=MP_PVE;
00345 if(pv_parse_format(&s, &(mp->u.p))<0) {
00346 LM_ERR("pv_parse_format failed for '%s'\n", (char *)(*param));
00347 pkg_free(mp);
00348 return -1;
00349 }
00350 }
00351 }
00352 *param = (void*)mp;
00353
00354 return 0;
00355 }
00356
00357
00364 static int avp_name_fixup(void ** param) {
00365 pv_spec_t avp_spec;
00366 struct multiparam_t *mp;
00367 str s;
00368
00369 s.s = (char *)(*param);
00370 s.len = strlen(s.s);
00371 if (s.len <= 0) return -1;
00372 if (pv_parse_spec(&s, &avp_spec)==0 || avp_spec.type!=PVT_AVP) {
00373 LM_ERR("Malformed or non AVP definition <%s>\n", (char *)(*param));
00374 return -1;
00375 }
00376
00377 mp = (struct multiparam_t *)pkg_malloc(sizeof(struct multiparam_t));
00378 if (mp == NULL) {
00379 PKG_MEM_ERROR;
00380 return -1;
00381 }
00382 memset(mp, 0, sizeof(struct multiparam_t));
00383
00384 mp->type=MP_AVP;
00385 if(pv_get_avp_name(0, &(avp_spec.pvp), &(mp->u.a.name), &(mp->u.a.flags))!=0) {
00386 LM_ERR("Invalid AVP definition <%s>\n", (char *)(*param));
00387 pkg_free(mp);
00388 return -1;
00389 }
00390
00391 *param = (void*)mp;
00392
00393 return 0;
00394 }
00395
00396
00397 static int pdb_query_fixup(void **arg, int arg_no)
00398 {
00399 if (arg_no == 1) {
00400
00401 if (mp_fixup(arg) < 0) {
00402 LM_ERR("cannot fixup parameter %d\n", arg_no);
00403 return -1;
00404 }
00405 }
00406 else if (arg_no == 2) {
00407
00408 if (avp_name_fixup(arg) < 0) {
00409 LM_ERR("cannot fixup parameter %d\n", arg_no);
00410 return -1;
00411 }
00412 }
00413
00414 return 0;
00415 }
00416
00417
00422 static int add_server(char *host, char *port)
00423 {
00424 long int ret;
00425 struct server_item_t *server;
00426
00427 LM_DBG("adding server '%s:%s'\n", host, port);
00428 server= pkg_malloc(sizeof(struct server_item_t));
00429 if (server == NULL) {
00430 PKG_MEM_ERROR;
00431 return -1;
00432 }
00433 memset(server, 0, sizeof(struct server_item_t));
00434
00435 server->next = server_list->head;
00436 server_list->head = server;
00437
00438 server->host = pkg_malloc(strlen(host)+1);
00439 if (server->host == NULL) {
00440 PKG_MEM_ERROR;
00441 return -1;
00442 }
00443 strcpy(server->host, host);
00444
00445 ret=strtol(port, NULL, 10);
00446 if ((ret<0) || (ret>65535)) {
00447 LM_ERR("invalid port '%s'\n", port);
00448 return -1;
00449 }
00450 server->port=ret;
00451
00452 return 0;
00453 }
00454
00455
00460 static int prepare_server(void)
00461 {
00462 char *p, *dst, *end, *sep, *host, *port;
00463
00464 if (modp_server == NULL) {
00465 LM_ERR("server parameter missing.\n");
00466 return -1;
00467 }
00468
00469
00470 for (p = modp_server, dst = modp_server; *p != '\0'; ++p, ++dst) {
00471 while (isspace(*p)) ++p;
00472 *dst = *p;
00473 }
00474 *dst = '\0';
00475
00476 p = modp_server;
00477 end = p + strlen(p);
00478
00479 while (p < end) {
00480 sep = strchr(p, ':');
00481 if (sep == NULL) {
00482 LM_ERR("syntax error in sources parameter.\n");
00483 return -1;
00484 }
00485 host = p;
00486 *sep = '\0';
00487 p = sep + 1;
00488
00489 sep = strchr(p, ',');
00490 if (sep == NULL) sep = end;
00491 port = p;
00492 *sep = '\0';
00493 p = sep + 1;
00494
00495 if (add_server(host, port) != 0) return -1;
00496 }
00497
00498 return 0;
00499 }
00500
00501
00502 static void destroy_server_list(void)
00503 {
00504 if (server_list) {
00505 while (server_list->head) {
00506 struct server_item_t *server = server_list->head;
00507 server_list->head = server->next;
00508 if (server->host) pkg_free(server->host);
00509 pkg_free(server);
00510 }
00511 pkg_free(server_list);
00512 server_list = NULL;
00513 }
00514 }
00515
00516
00521 static int init_server_list(void)
00522 {
00523 server_list = pkg_malloc(sizeof(struct server_list_t));
00524 if (server_list == NULL) {
00525 PKG_MEM_ERROR;
00526 return -1;
00527 }
00528 memset(server_list, 0, sizeof(struct server_list_t));
00529
00530 if (prepare_server() != 0) {
00531 destroy_server_list();
00532 return -1;
00533 }
00534
00535 return 0;
00536 }
00537
00538
00543 static int init_server_socket(void)
00544 {
00545 struct server_item_t *server;
00546 struct hostent *hp;
00547 int i;
00548
00549 if (server_list) {
00550 server_list->nserver=0;
00551 server = server_list->head;
00552 while (server) {
00553 LM_DBG("initializing socket for '%s:%d'\n", server->host, server->port);
00554 server->sock = socket(AF_INET, SOCK_DGRAM, 0);
00555 if (server->sock<0) {
00556 LM_ERR("socket() failed with errno=%d (%s).\n", errno, strerror(errno));
00557 return -1;
00558 }
00559
00560 memset(&(server->dstaddr), 0, sizeof(server->dstaddr));
00561 server->dstaddr.sin_family = AF_INET;
00562 server->dstaddr.sin_port = htons(server->port);
00563 hp = gethostbyname(server->host);
00564 if (hp == NULL) {
00565 LM_ERR("gethostbyname(%s) failed with h_errno=%d.\n", server->host, h_errno);
00566 close(server->sock);
00567 server->sock=0;
00568 return -1;
00569 }
00570 memcpy(&(server->dstaddr.sin_addr.s_addr), hp->h_addr, hp->h_length);
00571 server->dstaddrlen=sizeof(server->dstaddr);
00572
00573 server = server->next;
00574 server_list->nserver++;
00575 }
00576
00577 LM_DBG("got %d server in list\n", server_list->nserver);
00578 server_list->fds = pkg_malloc(sizeof(struct pollfd)*server_list->nserver);
00579 if (server_list->fds == NULL) {
00580 PKG_MEM_ERROR;
00581 return -1;
00582 }
00583 memset(server_list->fds, 0, sizeof(struct pollfd)*server_list->nserver);
00584
00585 i=0;
00586 server = server_list->head;
00587 while (server) {
00588 server_list->fds[i].fd=server->sock;
00589 server_list->fds[i].events=POLLIN;
00590 server = server->next;
00591 i++;
00592 }
00593 }
00594 return 0;
00595 }
00596
00597
00601 static void destroy_server_socket(void)
00602 {
00603 if (server_list) {
00604 struct server_item_t *server = server_list->head;
00605 while (server) {
00606 if (server->sock>0) close(server->sock);
00607 server = server->next;
00608 }
00609 if (server_list->fds) pkg_free(server_list->fds);
00610 }
00611 }
00612
00613
00614 struct mi_root * mi_pdb_status(struct mi_root* cmd, void* param)
00615 {
00616 struct mi_root * root = NULL;
00617 struct mi_node * node = NULL;
00618
00619 if (active == NULL) return init_mi_tree(500, "NULL pointer", 12);
00620
00621 root = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00622 if (root == NULL) return NULL;
00623
00624 if (*active) node = addf_mi_node_child(&root->node, 0, 0, 0, "pdb is active");
00625 else node = addf_mi_node_child(&root->node, 0, 0, 0, "pdb is deactivated");
00626 if (node == NULL) {
00627 free_mi_tree(root);
00628 return NULL;
00629 }
00630
00631 return root;
00632 }
00633
00634
00635 struct mi_root * mi_pdb_deactivate(struct mi_root* cmd, void* param)
00636 {
00637 if (active == NULL) return init_mi_tree(500, "NULL pointer", 12);
00638
00639 *active=0;
00640 return init_mi_tree(200, MI_OK_S, MI_OK_LEN);
00641 }
00642
00643
00644 struct mi_root * mi_pdb_activate(struct mi_root* cmd, void* param)
00645 {
00646 if (active == NULL) return init_mi_tree(500, "NULL pointer", 12);
00647
00648 *active=1;
00649 return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00650 }
00651
00652
00653 static int mod_init(void)
00654 {
00655 active = shm_malloc(sizeof(*active));
00656 if (active == NULL) {
00657 SHM_MEM_ERROR;
00658 return -1;
00659 }
00660 *active=1;
00661
00662 if (init_server_list() != 0) {
00663 shm_free(active);
00664 return -1;
00665 }
00666 return 0;
00667 }
00668
00669 static int child_init (int rank)
00670 {
00671 if(rank==PROC_INIT || rank==PROC_TCP_MAIN)
00672 return 0;
00673 return mi_child_init();
00674 }
00675
00676
00677 static int pdb_child_initialized = 0;
00678
00679 static int mi_child_init(void)
00680 {
00681 if(pdb_child_initialized)
00682 return 0;
00683 if (init_server_socket() != 0) return -1;
00684 pdb_child_initialized = 1;
00685 return 0;
00686 }
00687
00688
00689 static void mod_destroy(void)
00690 {
00691 destroy_server_socket();
00692 destroy_server_list();
00693 if (active) shm_free(active);
00694 }