00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00030 #include "conf.h"
00031 #include "../../mem/mem.h"
00032 #include "../../mem/shm_mem.h"
00033 #include "../../sr_module.h"
00034 #include "../../proxy.h"
00035 #include <ctype.h>
00036 #include <errno.h>
00037 #include <limits.h>
00038 #include <string.h>
00039 #include <stdlib.h>
00040 #include <stdio.h>
00041
00042 #define BUFSIZE 1000
00043
00045 enum {
00046 sfidx_request = 0,
00047 sfidx_reply,
00048 sfilter_cnt
00049 };
00050
00052 static int sfilter_mask[sfilter_cnt] = { 1, 2 };
00053
00055 static char *sfilter_str[sfilter_cnt] = {
00056 "REQUEST",
00057 "REPLY"
00058 };
00059
00060
00061 struct fwd_setting {
00062 int active;
00063 int sfilter;
00064 char *filter_methods;
00065 struct proxy_l* proxy;
00066 };
00067
00068
00069 static struct fwd_setting *fwd_settings = NULL;
00070 static int fwd_max_id = 0;
00071
00072
00079 static void remove_spaces(char *s)
00080 {
00081 char *p, *dst;
00082 for (p = s, dst = s; *p != '\0'; ++p) {
00083 if (!isspace(*p)) *dst++ = *p;
00084 }
00085 *dst = '\0';
00086
00087 }
00088
00089
00099 static int conf_str2int(char *s)
00100 {
00101 if (s == NULL) return -1;
00102
00103 errno = 0;
00104 char *end = NULL;
00105 long int i = strtol(s, &end, 10);
00106 if ((errno != 0) || (i == LONG_MIN) || (i == LONG_MAX) || (end == s)) {
00107 LM_ERR("invalid string '%s'.\n", s);
00108 return -1;
00109 }
00110
00111 return i;
00112 }
00113
00114
00124 int conf_str2id(char *id_str)
00125 {
00126 int id = conf_str2int(id_str);
00127
00128 if ((id<0) || (id > fwd_max_id)) {
00129 LM_ERR("id %d is out of range.\n", id);
00130 return -1;
00131 }
00132
00133 return id;
00134 }
00135
00136
00143 static int update_switch(int id, char* param_str)
00144 {
00145 if (param_str == NULL) {
00146 LM_ERR("param_str is NULL.\n");
00147 return -1;
00148 }
00149
00150 if (strcmp(param_str, "on") == 0) {
00151 fwd_settings[id].active = 1;
00152 return 0;
00153 } else if (strcmp(param_str, "off") == 0) {
00154 fwd_settings[id].active = 0;
00155 return 0;
00156 }
00157
00158 LM_ERR("invalid switch '%s'.\n", param_str);
00159 return -1;
00160 }
00161
00162
00173 static int update_filter(int id, char *flist)
00174 {
00175 if (flist == NULL) {
00176 LM_ERR("flist is NULL.\n");
00177 return -1;
00178 }
00179
00180
00181 fwd_settings[id].sfilter = 0;
00182 if (fwd_settings[id].filter_methods != NULL) {
00183 shm_free(fwd_settings[id].filter_methods);
00184 fwd_settings[id].filter_methods = NULL;
00185 }
00186
00187 int i;
00188 for (i=0; i<sfilter_cnt; i++) {
00189 if (strstr(flist, sfilter_str[i]) != NULL) {
00190
00191 fwd_settings[id].sfilter |= sfilter_mask[i];
00192 }
00193 }
00194
00195 char buf[BUFSIZE+1], tmp[BUFSIZE+1];
00196 buf[0] = '\0';
00197 char *set_p = flist;
00198 char *token = NULL;
00199 while ((token = strsep(&set_p, ":"))) {
00200 int found = 0;
00201
00202 for (i=0; i<sfilter_cnt; i++) {
00203 if (strcmp(token, sfilter_str[i]) == 0) {
00204 found = 1;
00205 break;
00206 }
00207 }
00208
00209 if (found == 0) {
00210
00211 if (buf[0]) {
00212 strcpy(tmp, buf);
00213 snprintf(buf, BUFSIZE, "%s:%s", tmp, token);
00214 buf[BUFSIZE]='\0';
00215 } else {
00216 snprintf(buf, BUFSIZE, "%s", token);
00217 buf[BUFSIZE]='\0';
00218 }
00219 }
00220 }
00221
00222 int len = strlen(buf);
00223 if (len > 0) {
00224 char *flc = shm_malloc(len+1);
00225 if (flc == NULL) {
00226 SHM_MEM_ERROR;
00227 return -1;
00228 }
00229 memcpy(flc, buf, len+1);
00230 fwd_settings[id].filter_methods = flc;
00231 }
00232 return 0;
00233 }
00234
00235
00243 static int update_proxy(int id, char *host_str, char *port_str)
00244 {
00245 if (host_str == NULL) {
00246 LM_ERR("host_str is NULL.\n");
00247 return -1;
00248 }
00249 if (port_str == NULL) {
00250 LM_ERR("port_str is NULL.\n");
00251 return -1;
00252 }
00253
00254 int port = conf_str2int(port_str);
00255 if (port < 0) {
00256 LM_ERR("invalid port '%s'.\n", port_str);
00257 return -1;
00258 }
00259
00260
00261 str host;
00262 host.len = strlen(host_str);
00263 host.s = shm_malloc(host.len+1);
00264 if (host.s == NULL) {
00265 SHM_MEM_ERROR;
00266 return -1;
00267 }
00268 strcpy(host.s, host_str);
00269
00270
00271 struct proxy_l* proxy;
00272 proxy = mk_shm_proxy(&host, port, PROTO_UDP);
00273 if (proxy == NULL) {
00274 LM_ERR("cannot make proxy (host='%s', port=%d).\n", host_str, port);
00275 shm_free(host.s);
00276 return -1;
00277 }
00278
00279 if (fwd_settings[id].proxy) {
00280
00281 if (fwd_settings[id].proxy->name.s) {
00282 shm_free(fwd_settings[id].proxy->name.s);
00283 }
00284 free_shm_proxy(fwd_settings[id].proxy);
00285 shm_free(fwd_settings[id].proxy);
00286 }
00287 fwd_settings[id].proxy = proxy;
00288
00289 return 0;
00290 }
00291
00292
00303 int conf_parse_switch(char *settings)
00304 {
00305
00306 int len = strlen(settings);
00307 if (len==0) return 1;
00308 char *strc = (char *)pkg_malloc(len+1);
00309 if (strc == NULL) {
00310 PKG_MEM_ERROR;
00311 return -1;
00312 }
00313 memcpy(strc, settings, len+1);
00314 remove_spaces(strc);
00315
00316 char *set_p = strc;
00317 char *token = NULL;
00318 while ((token = strsep(&set_p, ","))) {
00319 char *id_str = strsep(&token, "=");
00320 int id = conf_str2id(id_str);
00321 if (id < 0) {
00322 LM_ERR("cannot parse id '%s'.\n", id_str);
00323 pkg_free(strc);
00324 return -1;
00325 }
00326
00327
00328 if (update_switch(id, token) < 0) {
00329 LM_ERR("cannot update switch.\n");
00330 pkg_free(strc);
00331 return -1;
00332 }
00333 }
00334
00335 pkg_free(strc);
00336 return 1;
00337 }
00338
00339
00345 int conf_show(struct mi_root* rpl_tree)
00346 {
00347 int id, sfilter;
00348 struct mi_node * node = NULL;
00349
00350 node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "id switch %30s proxy\n", "filter");
00351 if(node == NULL)
00352 goto error;
00353
00354 for (id=0; id<=fwd_max_id; id++) {
00355 char buf[BUFSIZE+1];
00356 char tmp[BUFSIZE+1];
00357 buf[0]='\0';
00358 for (sfilter=0; sfilter<sfilter_cnt; sfilter++) {
00359 if (fwd_settings[id].sfilter&sfilter_mask[sfilter]) {
00360 if (buf[0]) {
00361 strcpy(tmp, buf);
00362 snprintf(buf, BUFSIZE, "%s:%s", tmp, sfilter_str[sfilter]);
00363 buf[BUFSIZE]='\0';
00364 } else {
00365 snprintf(buf, BUFSIZE, "%s", sfilter_str[sfilter]);
00366 buf[BUFSIZE]='\0';
00367 }
00368 }
00369 }
00370 if (fwd_settings[id].filter_methods) {
00371 if (buf[0]) {
00372 strcpy(tmp, buf);
00373 snprintf(buf, BUFSIZE, "%s:%s", tmp, fwd_settings[id].filter_methods);
00374 buf[BUFSIZE]='\0';
00375 } else {
00376 snprintf(buf, BUFSIZE, "%s", fwd_settings[id].filter_methods);
00377 buf[BUFSIZE]='\0';
00378 }
00379 }
00380 node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "%2d %s %33s %s:%d\n", id,
00381 fwd_settings[id].active ? "on " : "off", buf,
00382 fwd_settings[id].proxy ? fwd_settings[id].proxy->name.s : "",
00383 fwd_settings[id].proxy ? fwd_settings[id].proxy->port : 0);
00384 if(node == NULL)
00385 goto error;
00386
00387 }
00388 return 0;
00389
00390 error:
00391 return -1;
00392 }
00393
00394
00405 int conf_parse_filter(char *settings)
00406 {
00407
00408 int len = strlen(settings);
00409 if (len==0) return 1;
00410 char *strc = (char *)pkg_malloc(len+1);
00411 if (strc == NULL) {
00412 PKG_MEM_ERROR;
00413 return -1;
00414 }
00415 memcpy(strc, settings, len+1);
00416 remove_spaces(strc);
00417
00418 char *set_p = strc;
00419 char *token = NULL;
00420 while ((token = strsep(&set_p, ","))) {
00421 char *id_str = strsep(&token, "=");
00422 int id = conf_str2id(id_str);
00423 if (id<0) {
00424 LM_ERR("cannot parse id '%s'.\n", id_str);
00425 pkg_free(strc);
00426 return -1;
00427 }
00428 if (update_filter(id, token) < 0) {
00429 LM_ERR("cannot extract filters.\n");
00430 pkg_free(strc);
00431 return -1;
00432 }
00433 }
00434
00435 pkg_free(strc);
00436 return 1;
00437 }
00438
00439
00450 int conf_parse_proxy(char *settings)
00451 {
00452
00453 int len = strlen(settings);
00454 if (len==0) return 1;
00455 char *strc = (char *)pkg_malloc(len+1);
00456 if (strc == NULL) {
00457 PKG_MEM_ERROR;
00458 return -1;
00459 }
00460 memcpy(strc, settings, len+1);
00461 remove_spaces(strc);
00462
00463 char *set_p = strc;
00464 char *token = NULL;
00465 while ((token = strsep(&set_p, ","))) {
00466 char *id_str = strsep(&token, "=");
00467 int id = conf_str2id(id_str);
00468 if (id<0) {
00469 LM_ERR("cannot parse id '%s'.\n", id_str);
00470 pkg_free(strc);
00471 return -1;
00472 }
00473 char *host = strsep(&token, ":");
00474
00475
00476 if (update_proxy(id, host, token) < 0) {
00477 LM_ERR("cannot update proxy.\n");
00478 pkg_free(strc);
00479 return -1;
00480 }
00481 }
00482
00483 pkg_free(strc);
00484 return 1;
00485 }
00486
00487
00495 static int filter_methods_contains_request(int id, char *method, int method_len)
00496 {
00497 char *p = fwd_settings[id].filter_methods;
00498
00499 while (p != NULL) {
00500 if (strncmp(p, method, method_len) == 0) {
00501 return 1;
00502 }
00503 p = strchr(p, ':');
00504 if (p != NULL) p++;
00505 }
00506
00507 return 0;
00508 }
00509
00510
00517 struct proxy_l *conf_needs_forward(struct sip_msg *msg, int id)
00518 {
00519 if ((msg == NULL) || (fwd_settings[id].active == 0)) {
00520 return NULL;
00521 }
00522
00523 if (msg->first_line.type == SIP_REPLY) {
00524 if (fwd_settings[id].sfilter&sfilter_mask[sfidx_reply]) {
00525 return fwd_settings[id].proxy;
00526 }
00527 }
00528
00529 if (msg->first_line.type == SIP_REQUEST) {
00530 if (fwd_settings[id].sfilter&sfilter_mask[sfidx_request]) {
00531 return fwd_settings[id].proxy;
00532 }
00533
00534 if (filter_methods_contains_request(id, msg->first_line.u.request.method.s, msg->first_line.u.request.method.len) > 0) {
00535 return fwd_settings[id].proxy;
00536 }
00537 }
00538
00539 return NULL;
00540 }
00541
00542
00548 int conf_init(int max_id)
00549 {
00550
00551 fwd_settings = shm_malloc(sizeof(struct fwd_setting)*(max_id+1));
00552 if (fwd_settings == NULL) {
00553 SHM_MEM_ERROR;
00554 return -1;
00555 }
00556 memset(fwd_settings, 0, sizeof(struct fwd_setting)*(max_id+1));
00557 fwd_max_id = max_id;
00558 return 0;
00559 }
00560
00561
00565 void conf_destroy(void)
00566 {
00567 int id;
00568
00569 if (fwd_settings) {
00570 for (id=0; id<=fwd_max_id; id++) {
00571 fwd_settings[id].active = 0;
00572 if (fwd_settings[id].proxy) {
00573 if (fwd_settings[id].proxy->name.s) {
00574 shm_free(fwd_settings[id].proxy->name.s);
00575 }
00576 free_shm_proxy(fwd_settings[id].proxy);
00577 shm_free(fwd_settings[id].proxy);
00578 }
00579 }
00580 shm_free(fwd_settings);
00581 }
00582 }