cr_db.c

Go to the documentation of this file.
00001 /*
00002  * $Id$
00003  *
00004  * Copyright (C) 2007-2008 1&1 Internet AG
00005  *
00006  * This file is part of SIP-router, a free SIP server.
00007  *
00008  * SIP-router is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version
00012  *
00013  * SIP-router is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License 
00019  * along with this program; if not, write to the Free Software 
00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  */
00022 
00030 #include "../../dprint.h"
00031 #include "../../mem/mem.h"
00032 #include "../../mem/shm_mem.h"
00033 #include "carrierroute.h"
00034 #include "cr_db.h"
00035 #include "cr_carrier.h"
00036 #include "config.h"
00037 #include <stdio.h>
00038 #include <stdlib.h>
00039 
00040 #define QUERY_LEN 2048
00041 
00042 static char query[QUERY_LEN];
00043 
00044 str * columns[COLUMN_NUM] = { &carrierroute_id_col, &carrierroute_carrier_col,
00045         &carrierroute_domain_col,
00046         &carrierroute_scan_prefix_col,
00047         &carrierroute_flags_col,
00048         &carrierroute_mask_col,
00049         &carrierroute_prob_col,
00050         &carrierroute_rewrite_host_col,
00051         &carrierroute_strip_col,
00052         &carrierroute_rewrite_prefix_col,
00053         &carrierroute_rewrite_suffix_col,
00054         &carrierroute_description_col
00055 };
00056 
00057 str * carrier_name_columns[CARRIER_NAME_COLUMN_NUM] = {
00058         &carrier_name_id_col,
00059         &carrier_name_carrier_col
00060 };
00061 
00062 str * domain_name_columns[DOMAIN_NAME_COLUMN_NUM] = {
00063         &domain_name_id_col,
00064         &domain_name_domain_col
00065 };
00066 
00067 str * failure_columns[FAILURE_COLUMN_NUM] = {
00068         &carrierfailureroute_id_col,
00069         &carrierfailureroute_carrier_col,
00070         &carrierfailureroute_domain_col,
00071         &carrierfailureroute_scan_prefix_col,
00072         &carrierfailureroute_host_name_col,
00073         &carrierfailureroute_reply_code_col,
00074         &carrierfailureroute_flags_col,
00075         &carrierfailureroute_mask_col,
00076         &carrierfailureroute_next_domain_col,
00077         &carrierfailureroute_description_col
00078 };
00079 
00080 
00081 static int load_carrier_map(struct route_data_t *rd) {
00082         db1_res_t * res = NULL;
00083         int i, count;
00084         if(!rd){
00085                 LM_ERR("invalid parameter\n");
00086                 return -1;
00087         }
00088         if (carrierroute_dbf.use_table(carrierroute_dbh, &carrier_name_table) < 0) {
00089                 LM_ERR("couldn't use table\n");
00090                 return -1;
00091         }
00092 
00093         if (carrierroute_dbf.query(carrierroute_dbh, 0, 0, 0, (db_key_t *)carrier_name_columns, 0, CARRIER_NAME_COLUMN_NUM, 0, &res) < 0) {
00094                 LM_ERR("couldn't query table\n");
00095                 return -1;
00096         }
00097 
00098         count = RES_ROW_N(res);
00099         if (count == 0) {
00100                 LM_ERR("empty %.*s table", carrier_name_table.len, carrier_name_table.s);
00101                 carrierroute_dbf.free_result(carrierroute_dbh, res);
00102                 return 0;
00103         }
00104 
00105         rd->carrier_map = shm_malloc(sizeof(struct name_map_t) * count);
00106         if (rd->carrier_map == NULL) {
00107                 SHM_MEM_ERROR;
00108                 carrierroute_dbf.free_result(carrierroute_dbh, res);
00109                 return -1;
00110         }
00111         memset(rd->carrier_map, 0, sizeof(struct name_map_t) * count);
00112 
00113         for (i=0; i<count; i++) {
00114                 rd->carrier_map[i].id = res->rows[i].values[CARRIER_NAME_ID_COL].val.int_val;
00115                 rd->carrier_map[i].name.len = strlen(res->rows[i].values[CARRIER_NAME_NAME_COL].val.string_val);
00116                 rd->carrier_map[i].name.s = shm_malloc(rd->carrier_map[i].name.len);
00117                 if (rd->carrier_map[i].name.s == NULL) {
00118                         SHM_MEM_ERROR;
00119                         carrierroute_dbf.free_result(carrierroute_dbh, res);
00120                         shm_free(rd->carrier_map);
00121                         rd->carrier_map = NULL;
00122                         return -1;
00123                 }
00124                 memcpy(rd->carrier_map[i].name.s, res->rows[i].values[CARRIER_NAME_NAME_COL].val.string_val, rd->carrier_map[i].name.len);
00125         }
00126 
00127         /* sort carrier map by id for faster access */
00128         qsort(rd->carrier_map, count, sizeof(rd->carrier_map[0]), compare_name_map);
00129 
00130         carrierroute_dbf.free_result(carrierroute_dbh, res);
00131         return count;
00132 }
00133 
00134 
00135 
00136 
00137 static int load_domain_map(struct route_data_t *rd) {
00138         db1_res_t * res = NULL;
00139         int i, count;
00140         if(!rd){
00141                 LM_ERR("invalid parameter\n");
00142                 return -1;
00143         }
00144         if (carrierroute_dbf.use_table(carrierroute_dbh, &domain_name_table) < 0) {
00145                 LM_ERR("couldn't use table\n");
00146                 return -1;
00147         }
00148 
00149         if (carrierroute_dbf.query(carrierroute_dbh, 0, 0, 0, (db_key_t *)domain_name_columns, 0, DOMAIN_NAME_COLUMN_NUM, 0, &res) < 0) {
00150                 LM_ERR("couldn't query table\n");
00151                 return -1;
00152         }
00153 
00154         count = RES_ROW_N(res);
00155         if (count == 0) {
00156                 LM_ERR("empty %.*s table", domain_name_table.len, domain_name_table.s);
00157                 carrierroute_dbf.free_result(carrierroute_dbh, res);
00158                 return 0;
00159         }
00160 
00161         rd->domain_map = shm_malloc(sizeof(struct name_map_t) * count);
00162         if (rd->domain_map == NULL) {
00163                 SHM_MEM_ERROR;
00164                 carrierroute_dbf.free_result(carrierroute_dbh, res);
00165                 return -1;
00166         }
00167         memset(rd->domain_map, 0, sizeof(struct name_map_t) * count);
00168 
00169         for (i=0; i<count; i++) {
00170                 rd->domain_map[i].id = res->rows[i].values[DOMAIN_NAME_ID_COL].val.int_val;
00171                 rd->domain_map[i].name.len = strlen(res->rows[i].values[DOMAIN_NAME_NAME_COL].val.string_val);
00172                 rd->domain_map[i].name.s = shm_malloc(rd->domain_map[i].name.len);
00173                 if (rd->domain_map[i].name.s == NULL) {
00174                         SHM_MEM_ERROR;
00175                         carrierroute_dbf.free_result(carrierroute_dbh, res);
00176                         shm_free(rd->domain_map);
00177                         rd->domain_map = NULL;
00178                         return -1;
00179                 }
00180                 memcpy(rd->domain_map[i].name.s, res->rows[i].values[DOMAIN_NAME_NAME_COL].val.string_val, rd->domain_map[i].name.len);
00181         }
00182 
00183         /* sort domain map by id for faster access */
00184         qsort(rd->domain_map, count, sizeof(rd->domain_map[0]), compare_name_map);
00185 
00186         carrierroute_dbf.free_result(carrierroute_dbh, res);
00187         return count;
00188 }
00189 
00190 
00191 
00192 
00193 int load_user_carrier(str * user, str * domain) {
00194         db1_res_t * res;
00195         db_key_t cols[1];
00196         db_key_t keys[2];
00197         db_val_t vals[2];
00198         db_op_t op[2];
00199         int id;
00200         int use_domain = cfg_get(carrierroute, carrierroute_cfg, use_domain);
00201         if (!user || (use_domain  && !domain)) {
00202                 LM_ERR("NULL pointer in parameter\n");
00203                 return -1;
00204         }
00205 
00206         cols[0] = subscriber_columns[SUBSCRIBER_CARRIER_COL];
00207 
00208         keys[0] = subscriber_columns[SUBSCRIBER_USERNAME_COL];
00209         op[0] = OP_EQ;
00210         VAL_TYPE(vals) = DB1_STR;
00211         VAL_NULL(vals) = 0;
00212         VAL_STR(vals) = *user;
00213 
00214         keys[1] = subscriber_columns[SUBSCRIBER_DOMAIN_COL];
00215         op[1] = OP_EQ;
00216         VAL_TYPE(vals+1) = DB1_STR;
00217         VAL_NULL(vals+1) = 0;
00218         VAL_STR(vals+1) = *domain;
00219 
00220         if (carrierroute_dbf.use_table(carrierroute_dbh, &subscriber_table) < 0) {
00221                 LM_ERR("can't use table\n");
00222                 return -1;
00223         }
00224 
00225         if (carrierroute_dbf.query(carrierroute_dbh, keys, op, vals, cols, use_domain ? 2 : 1, 1, NULL, &res) < 0) {
00226                 LM_ERR("can't query database\n");
00227                 return -1;
00228         }
00229 
00230         if (RES_ROW_N(res) == 0) {
00231                 carrierroute_dbf.free_result(carrierroute_dbh, res);
00232                 return 0;
00233         }
00234 
00235         if (VAL_NULL(ROW_VALUES(RES_ROWS(res)))) {
00236                 carrierroute_dbf.free_result(carrierroute_dbh, res);
00237                 return 0;
00238         }
00239 
00240         id = VAL_INT(ROW_VALUES(RES_ROWS(res)));
00241         carrierroute_dbf.free_result(carrierroute_dbh, res);
00242         return id;
00243 }
00244 
00245 
00246 
00247 
00258 int load_route_data_db(struct route_data_t * rd) {
00259         db1_res_t * res = NULL;
00260         db_row_t * row = NULL;
00261         int i, ret;
00262         struct carrier_data_t * tmp_carrier_data;
00263         static str query_str;
00264         str tmp_scan_prefix, tmp_rewrite_host, tmp_rewrite_prefix,
00265                 tmp_rewrite_suffix, tmp_host_name, tmp_reply_code, tmp_comment;
00266 
00267         if( (strlen("SELECT DISTINCT  FROM  WHERE = ")
00268                         + carrierroute_table.len + columns[COL_DOMAIN]->len
00269                         + columns[COL_CARRIER]->len + 20) >  QUERY_LEN) {
00270                 LM_ERR("query too long\n");
00271                 return -1;
00272         }
00273 
00274         if((rd->carrier_num = load_carrier_map(rd)) <= 0){
00275                 LM_ERR("error while retrieving carriers\n");
00276                 goto errout;
00277         }
00278 
00279         if((rd->domain_num = load_domain_map(rd)) <= 0){
00280                 LM_ERR("error while retrieving domains\n");
00281                 goto errout;
00282         }
00283 
00284         if ((rd->carriers = shm_malloc(sizeof(struct carrier_data_t *) * rd->carrier_num)) == NULL) {
00285                 SHM_MEM_ERROR;
00286                 goto errout;
00287         }
00288         memset(rd->carriers, 0, sizeof(struct carrier_data_t *) * rd->carrier_num);
00289 
00290         for (i=0; i<rd->carrier_num; i++) {
00291                 memset(query, 0, QUERY_LEN);
00292                 ret = snprintf(query, QUERY_LEN, "SELECT DISTINCT %.*s FROM %.*s WHERE %.*s=%i",
00293                 columns[COL_DOMAIN]->len, columns[COL_DOMAIN]->s, carrierroute_table.len,
00294                 carrierroute_table.s, columns[COL_CARRIER]->len, columns[COL_CARRIER]->s, rd->carrier_map[i].id);
00295                 if (ret < 0) {
00296                         LM_ERR("error in snprintf");
00297                         goto errout;
00298                 }
00299                 query_str.s = query;
00300                 query_str.len = ret;
00301 
00302                 if (carrierroute_dbf.raw_query(carrierroute_dbh, &query_str, &res) < 0) {
00303                         LM_ERR("Failed to query database.\n");
00304                         goto errout;
00305                 }
00306                 LM_INFO("carrier '%.*s' (id %i) has %i domains\n", rd->carrier_map[i].name.len, rd->carrier_map[i].name.s, rd->carrier_map[i].id, RES_ROW_N(res));
00307                 tmp_carrier_data = create_carrier_data(rd->carrier_map[i].id, &rd->carrier_map[i].name, RES_ROW_N(res));
00308                 if (tmp_carrier_data == NULL) {
00309                         LM_ERR("can't create new carrier '%.*s'\n", rd->carrier_map[i].name.len, rd->carrier_map[i].name.s);
00310                         goto errout;
00311                 }
00312                 if (add_carrier_data(rd, tmp_carrier_data) < 0) {
00313                         LM_ERR("can't add carrier '%.*s'\n", rd->carrier_map[i].name.len, rd->carrier_map[i].name.s);
00314                         destroy_carrier_data(tmp_carrier_data);
00315                         goto errout;
00316                 }
00317                 carrierroute_dbf.free_result(carrierroute_dbh, res);
00318                 res = NULL;
00319         }
00320 
00321         if (carrierroute_dbf.use_table(carrierroute_dbh, &carrierroute_table) < 0) {
00322                 LM_ERR("Cannot set database table '%.*s'.\n", carrierroute_table.len, carrierroute_table.s);
00323                 return -1;
00324         }
00325 
00326         if (DB_CAPABILITY(carrierroute_dbf, DB_CAP_FETCH)) {
00327                 if (carrierroute_dbf.query(carrierroute_dbh, NULL, NULL, NULL, (db_key_t *) columns, 0,
00328                                         COLUMN_NUM, NULL, NULL) < 0) {
00329                         LM_ERR("Failed to query database to prepare fetch row.\n");
00330                         return -1;
00331                 }
00332                 if(carrierroute_dbf.fetch_result(carrierroute_dbh, &res, cfg_get(carrierroute, carrierroute_cfg, fetch_rows)) < 0) {
00333                         LM_ERR("Fetching rows failed\n");
00334                         return -1;
00335                 }
00336         } else {
00337                 if (carrierroute_dbf.query(carrierroute_dbh, NULL, NULL, NULL, (db_key_t *) columns, 0,
00338                                  COLUMN_NUM, NULL, &res) < 0) {
00339                         LM_ERR("Failed to query database.\n");
00340                         return -1;
00341                 }
00342         }
00343         int n = 0;
00344         do {
00345                 LM_DBG("loading, cycle %d", n++);
00346                 for (i = 0; i < RES_ROW_N(res); ++i) {
00347                         row = &RES_ROWS(res)[i];
00348                         tmp_scan_prefix.s=(char *)row->values[COL_SCAN_PREFIX].val.string_val;
00349                         tmp_rewrite_host.s=(char *)row->values[COL_REWRITE_HOST].val.string_val;
00350                         tmp_rewrite_prefix.s=(char *)row->values[COL_REWRITE_PREFIX].val.string_val;
00351                         tmp_rewrite_suffix.s=(char *)row->values[COL_REWRITE_SUFFIX].val.string_val;
00352                         tmp_comment.s=(char *)row->values[COL_COMMENT].val.string_val;
00353                         if (tmp_scan_prefix.s==NULL) tmp_scan_prefix.s="";
00354                         if (tmp_rewrite_host.s==NULL) tmp_rewrite_host.s="";
00355                         if (tmp_rewrite_prefix.s==NULL) tmp_rewrite_prefix.s="";
00356                         if (tmp_rewrite_suffix.s==NULL) tmp_rewrite_suffix.s="";
00357                         if (tmp_comment.s==NULL) tmp_comment.s="";
00358                         tmp_scan_prefix.len=strlen(tmp_scan_prefix.s);
00359                         tmp_rewrite_host.len=strlen(tmp_rewrite_host.s);
00360                         tmp_rewrite_prefix.len=strlen(tmp_rewrite_prefix.s);
00361                         tmp_rewrite_suffix.len=strlen(tmp_rewrite_suffix.s);
00362                         tmp_comment.len=strlen(tmp_comment.s);
00363                         if (add_route(rd,
00364                                         row->values[COL_CARRIER].val.int_val,
00365                                         row->values[COL_DOMAIN].val.int_val,
00366                                         &tmp_scan_prefix,
00367                                         row->values[COL_FLAGS].val.int_val,
00368                                         row->values[COL_MASK].val.int_val,
00369                                         0,
00370                                         row->values[COL_PROB].val.double_val,
00371                                         &tmp_rewrite_host,
00372                                         row->values[COL_STRIP].val.int_val,
00373                                         &tmp_rewrite_prefix,
00374                                         &tmp_rewrite_suffix,
00375                                         1,
00376                                         0,
00377                                         -1,
00378                                         NULL,
00379                                         &tmp_comment) == -1) {
00380                                 goto errout;
00381                         }
00382                 }
00383                 if (DB_CAPABILITY(carrierroute_dbf, DB_CAP_FETCH)) {
00384                         if(carrierroute_dbf.fetch_result(carrierroute_dbh, &res,  cfg_get(carrierroute, carrierroute_cfg, fetch_rows)) < 0) {
00385                                 LM_ERR("fetching rows failed\n");
00386                                 carrierroute_dbf.free_result(carrierroute_dbh, res);
00387                                 return -1;
00388                         }
00389                 } else {
00390                         break;
00391                 }
00392         } while(RES_ROW_N(res) > 0);
00393 
00394         carrierroute_dbf.free_result(carrierroute_dbh, res);
00395         res = NULL;
00396         
00397         if (carrierroute_dbf.use_table(carrierroute_dbh, &carrierfailureroute_table) < 0) {
00398                 LM_ERR("cannot set database table '%.*s'.\n",
00399                                 carrierfailureroute_table.len, carrierfailureroute_table.s);
00400                 return -1;
00401         }
00402         if (carrierroute_dbf.query(carrierroute_dbh, NULL, NULL, NULL, (db_key_t *)failure_columns, 0,
00403                                                                 FAILURE_COLUMN_NUM, NULL, &res) < 0) {
00404                 LM_ERR("failed to query database.\n");
00405                 return -1;
00406         }
00407         for (i = 0; i < RES_ROW_N(res); ++i) {
00408                 row = &RES_ROWS(res)[i];
00409                 tmp_scan_prefix.s=(char *)row->values[FCOL_SCAN_PREFIX].val.string_val;
00410                 tmp_host_name.s=(char *)row->values[FCOL_HOST_NAME].val.string_val;
00411                 tmp_reply_code.s=(char *)row->values[FCOL_REPLY_CODE].val.string_val;
00412                 tmp_comment.s=(char *)row->values[FCOL_COMMENT].val.string_val;
00413                 if (tmp_scan_prefix.s==NULL) tmp_scan_prefix.s="";
00414                 if (tmp_host_name.s==NULL) tmp_host_name.s="";
00415                 if (tmp_reply_code.s==NULL) tmp_reply_code.s="";
00416                 if (tmp_comment.s==NULL) tmp_comment.s="";
00417                 tmp_scan_prefix.len=strlen(tmp_scan_prefix.s);
00418                 tmp_host_name.len=strlen(tmp_host_name.s);
00419                 tmp_reply_code.len=strlen(tmp_reply_code.s);
00420                 tmp_comment.len=strlen(tmp_comment.s);
00421                 if (add_failure_route(rd,
00422                                 row->values[FCOL_CARRIER].val.int_val,
00423                                 row->values[COL_DOMAIN].val.int_val,
00424                                 &tmp_scan_prefix,
00425                                 &tmp_host_name,
00426                                 &tmp_reply_code,
00427                                 row->values[FCOL_FLAGS].val.int_val,
00428                                 row->values[FCOL_MASK].val.int_val,
00429                                 row->values[FCOL_NEXT_DOMAIN].val.int_val,
00430                                 &tmp_comment) == -1) {
00431                         goto errout;
00432                 }
00433         }
00434 
00435         carrierroute_dbf.free_result(carrierroute_dbh, res);
00436         return 0;
00437 
00438 errout:
00439         if (res) {
00440                 carrierroute_dbf.free_result(carrierroute_dbh, res);
00441         }
00442         return -1;
00443 }