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