/* * Reload domain table to new hash table and when done, make new hash table * current one. */ int reload_domain_table ( void ) { /* db_key_t keys[] = {domain_col}; */ db_val_t vals[1]; db_key_t cols[1]; db_res_t* res; db_row_t* row; db_val_t* val; struct domain_list **new_hash_table; int i; cols[0] = domain_col.s; if (domain_dbf.use_table(db_handle, domain_table.s) < 0) { LOG(L_ERR, "reload_domain_table(): Error while trying to use domain table\n"); return -1; } VAL_TYPE(vals) = DB_STR; VAL_NULL(vals) = 0; if (domain_dbf.query(db_handle, NULL, 0, NULL, cols, 0, 1, 0, &res) < 0) { LOG(L_ERR, "reload_domain_table(): Error while querying database\n"); return -1; } /* Choose new hash table and free its old contents */ if (*hash_table == hash_table_1) { hash_table_free(hash_table_2); new_hash_table = hash_table_2; } else { hash_table_free(hash_table_1); new_hash_table = hash_table_1; } row = RES_ROWS(res); DBG("Number of rows in domain table: %d\n", RES_ROW_N(res)); for (i = 0; i < RES_ROW_N(res); i++) { val = ROW_VALUES(row + i); if ((ROW_N(row) == 1) && (VAL_TYPE(val) == DB_STRING)) { DBG("Value: %s inserted into domain hash table\n", VAL_STRING(val)); if (hash_table_install(new_hash_table, (char *)(VAL_STRING(val))) == -1) { LOG(L_ERR, "domain_reload(): Hash table problem\n"); domain_dbf.free_result(db_handle, res); return -1; } } else { LOG(L_ERR, "domain_reload(): Database problem\n"); domain_dbf.free_result(db_handle, res); return -1; } } domain_dbf.free_result(db_handle, res); *hash_table = new_hash_table; return 1; }
/* * Convert data fron db format to internal format */ static int convert_row(db_res_t* _res, db_row_t* _r, dmap_t* _d) { unsigned i, n = RES_COL_N(_res); ROW_N(_r) = n; for (i = 0; i < n; i++) { static const str dummy_string = {"", 0}; db_val_t* v = &ROW_VALUES(_r)[i]; db_type_t t = RES_TYPES(_res)[i]; if (_d->ind[i] == -1) { /* Initialize the string pointers to a dummy empty * string so that we do not crash when the NULL flag * is set but the module does not check it properly */ VAL_STRING(v) = dummy_string.s; VAL_STR(v) = dummy_string; VAL_BLOB(v) = dummy_string; VAL_TYPE(v) = t; VAL_NULL(v) = 1; continue; } if (_d->ind[i]) LM_WARN("truncated value in DB\n"); VAL_TYPE(v) = t; switch (t) { case DB_INT: VAL_INT(v) = *_d->pv[i].i; break; case DB_BIGINT: VAL_BIGINT(v) = *_d->pv[i].i; break; case DB_BITMAP: VAL_BITMAP(v) = *_d->pv[i].i; break; case DB_DOUBLE: VAL_DOUBLE(v) = *_d->pv[i].f; break; case DB_DATETIME: { struct tm tm; memset(&tm, 0, sizeof(tm)); OCIDateGetTime(_d->pv[i].o, &tm.tm_hour, &tm.tm_min, &tm.tm_sec); OCIDateGetDate(_d->pv[i].o, &tm.tm_year, &tm.tm_mon, &tm.tm_mday); if (tm.tm_mon) --tm.tm_mon; if (tm.tm_year >= 1900) tm.tm_year -= 1900; VAL_TIME(v) = mktime(&tm); } break; case DB_STR: case DB_BLOB: case DB_STRING: { size_t len = _d->len[i]; char *pstr = pkg_malloc(len+1); if (pstr == NULL) return -1; memcpy(pstr, _d->pv[i].c, len); pstr[len] = '\0'; VAL_FREE(v) = 1; if (t == DB_STR) { VAL_STR(v).s = pstr; VAL_STR(v).len = len; } else if (t == DB_BLOB) { VAL_BLOB(v).s = pstr; VAL_BLOB(v).len = len; } else { VAL_STRING(v) = pstr; } } break; default: LM_ERR("unknown type mapping (%u)\n", t); return -2; } } return 0; }
/*! * \brief Convert rows from mongodb to db API representation * \param _h database connection * \param _r database result set * \return 0 on success, negative on failure */ static int db_mongodb_convert_bson(const db1_con_t* _h, db1_res_t* _r, int _row, const bson_t *_rdoc) { static str dummy_string = {"", 0}; int col; db_mongodb_result_t *mgres; const char *colname; bson_type_t coltype; bson_iter_t riter; bson_iter_t citer; bson_iter_t *piter; db_val_t* dval; uint32_t i32tmp; bson_subtype_t subtype; bson_t *cdoc; mgres = (db_mongodb_result_t*)RES_PTR(_r); if(mgres->nrcols==0) { LM_ERR("no fields to convert\n"); return -1; } if(mgres->colsdoc==NULL) { cdoc = (bson_t*)_rdoc; } else { cdoc = (bson_t*)mgres->colsdoc; } if (!bson_iter_init (&citer, cdoc)) { LM_ERR("failed to initialize columns iterator\n"); return -3; } if(mgres->colsdoc) { if (!bson_iter_init (&riter, _rdoc)) { LM_ERR("failed to initialize result iterator\n"); return -3; } } if (db_allocate_row(_r, &(RES_ROWS(_r)[_row])) != 0) { LM_ERR("could not allocate row: %d\n", _row); return -2; } col = 0; while (bson_iter_next (&citer)) { if(col >= RES_COL_N(_r)) { LM_ERR("invalid number of columns (%d/%d)\n", col, RES_COL_N(_r)); return -4; } colname = bson_iter_key (&citer); LM_DBG("looking for field[%d] named: %s\n", col, colname); if(mgres->colsdoc) { if(!bson_iter_find(&riter, colname)) { LM_ERR("field [%s] not found in result iterator\n", colname); return -4; } piter = &riter; } else { piter = &citer; } coltype = bson_iter_type(piter); dval = &(ROW_VALUES(&(RES_ROWS(_r)[_row]))[col]); VAL_TYPE(dval) = RES_TYPES(_r)[col]; switch(coltype) { case BSON_TYPE_BOOL: VAL_INT(dval) = (int)bson_iter_bool (piter); break; case BSON_TYPE_INT32: VAL_INT(dval) = bson_iter_int32 (piter); break; case BSON_TYPE_TIMESTAMP: bson_iter_timestamp (piter, (uint32_t*)&VAL_INT(dval), &i32tmp); break; case BSON_TYPE_INT64: VAL_BIGINT(dval) = bson_iter_int64 (piter); break; case BSON_TYPE_DOUBLE: VAL_DOUBLE(dval) = bson_iter_double (piter); break; case BSON_TYPE_DATE_TIME: VAL_TIME(dval) = (time_t)(bson_iter_date_time (piter)/1000); break; case BSON_TYPE_BINARY: bson_iter_binary (piter, &subtype, (uint32_t*)&VAL_BLOB(dval).len, (const uint8_t**)&VAL_BLOB(dval).s); break; case BSON_TYPE_UTF8: VAL_STRING(dval) = (char*)bson_iter_utf8 (piter, &i32tmp); break; case BSON_TYPE_OID: break; case BSON_TYPE_NULL: memset(dval, 0, sizeof(db_val_t)); /* Initialize the string pointers to a dummy empty * string so that we do not crash when the NULL flag * is set but the module does not check it properly */ VAL_STRING(dval) = dummy_string.s; VAL_STR(dval) = dummy_string; VAL_BLOB(dval) = dummy_string; VAL_TYPE(dval) = RES_TYPES(_r)[col]; VAL_NULL(dval) = 1; break; #if 0 case BSON_TYPE_EOD: case BSON_TYPE_DOCUMENT: case BSON_TYPE_ARRAY: case BSON_TYPE_UNDEFINED: case BSON_TYPE_REGEX: case BSON_TYPE_DBPOINTER: case BSON_TYPE_CODE: case BSON_TYPE_SYMBOL: case BSON_TYPE_CODEWSCOPE: case BSON_TYPE_MAXKEY: case BSON_TYPE_MINKEY: #endif default: LM_WARN("unhandled data type column (%.*s) type id (%d), " "use DB1_STRING as default\n", RES_NAMES(_r)[col]->len, RES_NAMES(_r)[col]->s, coltype); RES_TYPES(_r)[col] = DB1_STRING; break; } LM_DBG("RES_NAMES(%p)[%d]=[%.*s] (%d)\n", RES_NAMES(_r)[col], col, RES_NAMES(_r)[col]->len, RES_NAMES(_r)[col]->s, coltype); col++; } return 0; }
/*compile the expressions, and if ok, build the rule */ dpl_node_t * build_rule(db_val_t * values) { tmrec_t *parsed_timerec; pcre * match_comp, *subst_comp; struct subst_expr * repl_comp; dpl_node_t * new_rule; str match_exp, subst_exp, repl_exp, attrs, timerec; int matchop; int namecount; matchop = VAL_INT(values+2); if((matchop != REGEX_OP) && (matchop!=EQUAL_OP)){ LM_ERR("invalid value for match operator\n"); return NULL; } parsed_timerec = 0; match_comp = subst_comp = 0; repl_comp = 0; new_rule = 0; GET_STR_VALUE(match_exp, values, 3, 0); if(matchop == REGEX_OP){ LM_DBG("Compiling %.*s expression with flag: %d\n", match_exp.len, match_exp.s, VAL_INT(values+4)); match_comp = wrap_pcre_compile(match_exp.s, VAL_INT(values+4)); if(!match_comp){ LM_ERR("failed to compile match expression \"%.*s\"\n", match_exp.len, match_exp.s); goto err; } } LM_DBG("building subst rule\n"); GET_STR_VALUE(subst_exp, values, 5, 1); if(!VAL_NULL(values+5) && subst_exp.s && subst_exp.len){ /* subst regexp */ subst_comp = wrap_pcre_compile(subst_exp.s, VAL_INT(values+4)); if(subst_comp == NULL){ LM_ERR("failed to compile subst expression \"%.*s\"\n", subst_exp.len, subst_exp.s); goto err; } } /* replace exp */ GET_STR_VALUE(repl_exp, values, 6, 1); if(!VAL_NULL(values+6) && repl_exp.len && repl_exp.s){ repl_comp = repl_exp_parse(repl_exp); if(!repl_comp){ LM_ERR("failed to compile replacing expression \"%.*s\"\n", repl_exp.len, repl_exp.s); goto err; } } pcre_fullinfo( subst_comp, /* the compiled pattern */ NULL, /* no extra data - we didn't study the pattern */ PCRE_INFO_CAPTURECOUNT, /* number of named substrings */ &namecount); /* where to put the answer */ LM_DBG("references:%d , max:%d\n",namecount, repl_comp?repl_comp->max_pmatch:0); if ( (repl_comp!=NULL) && (namecount<repl_comp->max_pmatch) && (repl_comp->max_pmatch!=0) ){ LM_ERR("repl_exp uses a non existing subexpression\n"); goto err; } new_rule = (dpl_node_t *)shm_malloc(sizeof(dpl_node_t)); if(!new_rule){ LM_ERR("out of shm memory(new_rule)\n"); goto err; } memset(new_rule, 0, sizeof(dpl_node_t)); if(str_to_shm(match_exp, &new_rule->match_exp)!=0) goto err; if (subst_comp) if(str_to_shm(subst_exp, &new_rule->subst_exp)!=0) goto err; if (repl_comp) if(str_to_shm(repl_exp, &new_rule->repl_exp)!=0) goto err; /*set the rest of the rule fields*/ new_rule->dpid = VAL_INT(values); new_rule->pr = VAL_INT(values+1); new_rule->match_flags = VAL_INT(values+4); new_rule->matchop = matchop; /* attributes */ GET_STR_VALUE(attrs, values, 7, 1); if( !VAL_NULL(values+7) && attrs.len && attrs.s) { if(str_to_shm(attrs, &new_rule->attrs)!=0) goto err; LM_DBG("attrs are %.*s\n", new_rule->attrs.len, new_rule->attrs.s); } /* Retrieve and Parse Timerec Matching Pattern */ GET_STR_VALUE(timerec, values, 8, 1); if( !VAL_NULL(values+8) && timerec.len && timerec.s) { parsed_timerec = parse_time_def(timerec.s); if(!parsed_timerec) { LM_ERR("failed to parse timerec pattern %.*s\n", timerec.len, timerec.s); goto err; } if(str_to_shm(timerec, &new_rule->timerec) != 0) goto err; new_rule->parsed_timerec = parsed_timerec; LM_DBG("timerecs are %.*s\n", new_rule->timerec.len, new_rule->timerec.s); } if (match_comp) new_rule->match_comp = match_comp; if (subst_comp) new_rule->subst_comp = subst_comp; if (repl_comp) new_rule->repl_comp = repl_comp; return new_rule; err: if(parsed_timerec) shm_free(parsed_timerec); if(match_comp) wrap_pcre_free(match_comp); if(subst_comp) wrap_pcre_free(subst_comp); if(repl_comp) repl_expr_free(repl_comp); if(new_rule) destroy_rule(new_rule); return NULL; }
int load_handles(db_func_t * dbf, db1_con_t * dbh) { static char query[UL_DB_QUERY_LEN]; db1_res_t * res; db_row_t * row; ul_db_handle_list_t * element; int i, id, query_len; str tmp; if(!dbf || !dbh){ LM_ERR("NULL parameter passed \n"); return -1; } query_len = 25 + id_col.len + reg_table.len; if(query_len > UL_DB_QUERY_LEN) { LM_ERR("weird: query larger than %i bytes.\n", UL_DB_QUERY_LEN); return -1; } memset(query, 0, UL_DB_QUERY_LEN); if (sprintf(query, "SELECT DISTINCT " "%.*s " "FROM " "%.*s", id_col.len, id_col.s, reg_table.len, reg_table.s) < 0) { LM_ERR("could not print query\n"); return -1; } tmp.s = query; tmp.len = strlen(query); if (dbf->raw_query (dbh, &tmp, &res) < 0) { LM_ERR("in database query.\n"); return -1; } if (RES_ROW_N (res) == 0) { dbf->free_result (dbh, res); LM_DBG ("no data found\n"); return 1; } for (i = 0; i < RES_ROW_N (res); ++i) { row = RES_ROWS (res) + i; if((element = allocate_handle_list()) == NULL) { LM_ERR("couldnt allocate handle.\n"); goto errout; } if (VAL_NULL (ROW_VALUES(row) + 0)) { LM_ERR("Weird: Empty ID-Field\n"); goto errout; } id = VAL_INT (ROW_VALUES(row) + 0); if(load_data(dbf, dbh, element->handle, id) < 0){ LM_ERR("couldn't load handle data.\n"); goto errout; } element->next = db_handles; db_handles = element; } dbf->free_result (dbh, res); return 0; errout: dbf->free_result (dbh, res); return -1; }
int uac_reg_db_refresh(str *pl_uuid) { db1_con_t *reg_db_con = NULL; db_func_t reg_dbf; reg_uac_t reg; db_key_t db_cols[10] = { &l_uuid_column, &l_username_column, &l_domain_column, &r_username_column, &r_domain_column, &realm_column, &auth_username_column, &auth_password_column, &auth_proxy_column, &expires_column }; db_key_t db_keys[1] = {&l_uuid_column}; db_val_t db_vals[1]; db1_res_t* db_res = NULL; int i, ret; /* binding to db module */ if(reg_db_url.s==NULL) { LM_ERR("no db url\n"); return -1; } if(db_bind_mod(®_db_url, ®_dbf)) { LM_ERR("database module not found\n"); return -1; } if (!DB_CAPABILITY(reg_dbf, DB_CAP_ALL)) { LM_ERR("database module does not " "implement all functions needed by the module\n"); return -1; } /* open a connection with the database */ reg_db_con = reg_dbf.init(®_db_url); if(reg_db_con==NULL) { LM_ERR("failed to connect to the database\n"); return -1; } if (reg_dbf.use_table(reg_db_con, ®_db_table) < 0) { LM_ERR("failed to use_table\n"); return -1; } db_vals[0].type = DB1_STR; db_vals[0].nul = 0; db_vals[0].val.str_val.s = pl_uuid->s; db_vals[0].val.str_val.len = pl_uuid->len; if((ret=reg_dbf.query(reg_db_con, db_keys, NULL, db_vals, db_cols, 1 /*nr keys*/, 10 /*nr cols*/, 0, &db_res))!=0 || RES_ROW_N(db_res)<=0 ) { reg_dbf.free_result(reg_db_con, db_res); if( ret==0) { return 0; } else { goto error; } } memset(®, 0, sizeof(reg_uac_t));; i = 0; /* check for NULL values ?!?! */ reg_db_set_attr(l_uuid, 0); reg_db_set_attr(l_username, 1); reg_db_set_attr(l_domain, 2); reg_db_set_attr(r_username, 3); reg_db_set_attr(r_domain, 4); /* realm may be empty */ if(!VAL_NULL(&RES_ROWS(db_res)[i].values[5])) { reg.realm.s = (char*)(RES_ROWS(db_res)[i].values[5].val.string_val); reg.realm.len = strlen(reg.realm.s); } reg_db_set_attr(auth_username, 6); reg_db_set_attr(auth_password, 7); reg_db_set_attr(auth_proxy, 8); reg.expires = (unsigned int)RES_ROWS(db_res)[i].values[9].val.int_val; reg.h_uuid = reg_compute_hash(®.l_uuid); reg.h_user = reg_compute_hash(®.l_username); lock_get(_reg_htable_gc_lock); if(reg_ht_get_byuuid(pl_uuid)!=NULL) { if(reg_ht_update_password(®)<0) { lock_release(_reg_htable_gc_lock); LM_ERR("Error updating reg to htable\n"); goto error; } } else { if(reg_ht_add(®)<0) { lock_release(_reg_htable_gc_lock); LM_ERR("Error adding reg to htable\n"); goto error; } } lock_release(_reg_htable_gc_lock); reg_dbf.free_result(reg_db_con, db_res); reg_dbf.close(reg_db_con); return 0; error: if (reg_db_con) { reg_dbf.free_result(reg_db_con, db_res); reg_dbf.close(reg_db_con); } return -1; }
/* * Insert a row into specified table * h: structure representing database connection * k: key names * v: values of the keys * n: number of key=value pairs */ int flat_db_insert(db_con_t* h, db_key_t* k, db_val_t* v, int n) { FILE* f; int i; char delims[4], *s; size_t len; f = CON_FILE(h); if (!f) { LOG(L_CRIT, "BUG: flat_db_insert: Uninitialized connection\n"); return -1; } if (local_timestamp < *flat_rotate) { flat_rotate_logs(); local_timestamp = *flat_rotate; } for(i = 0; i < n; i++) { if (!VAL_NULL(v + i)) { // TODO: how to distinguish NULL from empty switch(VAL_TYPE(v + i)) { case DB_INT: fprintf(f, "%d", VAL_INT(v + i)); break; case DB_FLOAT: fprintf(f, "%f", VAL_FLOAT(v + i)); break; case DB_DOUBLE: fprintf(f, "%f", VAL_DOUBLE(v + i)); break; case DB_STRING: { s = (char*) VAL_STRING(v + i); delims[0] = flat_delimiter[0]; delims[1] = flat_record_delimiter[0]; delims[2] = flat_escape[0]; delims[3] = '\0'; while (*s) { len = strcspn(s, delims); fprintf(f, "%.*s", (int)len, s); s+= len; if (*s) { fprintf(f, "%c%c", flat_escape[0], *s); s++; } } break; } case DB_STR: case DB_BLOB: if (VAL_TYPE(v + i) == DB_STR) { s = VAL_STR(v + i).s; len = VAL_STR(v + i).len; } else { s = VAL_BLOB(v + i).s; len = VAL_BLOB(v + i).len; } while (len > 0) { char *c; for (c = s; len > 0 && *c != flat_delimiter[0] && *c != flat_record_delimiter[0] && *c != flat_escape[0]; c++, len--); fprintf(f, "%.*s", (int)(c-s), s); s = c; if (len > 0) { fprintf(f, "%c%c", flat_escape[0], *s); s++; len--; } } break; case DB_DATETIME: fprintf(f, "%u", (unsigned int)VAL_TIME(v + i)); break; case DB_BITMAP: fprintf(f, "%u", VAL_BITMAP(v + i)); break; } } if (i < (n - 1)) { fprintf(f, "%c", flat_delimiter[0]); } } fprintf(f, "%c", flat_record_delimiter[0]); if (flat_flush) { fflush(f); } return 0; }
/*! * \brief SQL REPLACE implementation * \param _h structure representing database connection * \param _k key names * \param _v values of the keys * \param _n number of key=value pairs * \param _un number of keys to build the unique key, starting from first * \param _m mode - first update, then insert, or first insert, then update * \return 0 on success, negative on failure */ int db_postgres_replace(const db1_con_t* _h, const db_key_t* _k, const db_val_t* _v, const int _n, const int _un, const int _m) { unsigned int pos = 0; int i; if(_un > _n) { LM_ERR("number of columns for unique key is too high\n"); return -1; } if(_un > 0) { for(i=0; i<_un; i++) { if(!VAL_NULL(&_v[i])) { switch(VAL_TYPE(&_v[i])) { case DB1_INT: pos += VAL_UINT(&_v[i]); break; case DB1_STR: pos += get_hash1_raw((VAL_STR(&_v[i])).s, (VAL_STR(&_v[i])).len); break; case DB1_STRING: pos += get_hash1_raw(VAL_STRING(&_v[i]), strlen(VAL_STRING(&_v[i]))); break; default: break; } } } pos &= (_pg_lock_size-1); lock_set_get(_pg_lock_set, pos); if(db_postgres_update(_h, _k, 0, _v, _k + _un, _v + _un, _un, _n -_un)< 0) { LM_ERR("update failed\n"); lock_set_release(_pg_lock_set, pos); return -1; } if (db_postgres_affected_rows(_h) <= 0) { if(db_postgres_insert(_h, _k, _v, _n)< 0) { LM_ERR("insert failed\n"); lock_set_release(_pg_lock_set, pos); return -1; } LM_DBG("inserted new record in database table\n"); } else { LM_DBG("updated record in database table\n"); } lock_set_release(_pg_lock_set, pos); } else { if(db_postgres_insert(_h, _k, _v, _n)< 0) { LM_ERR("direct insert failed\n"); return -1; } LM_DBG("directly inserted new record in database table\n"); } return 0; }
void dialog_update_db(unsigned int ticks, void * param) { static db_ps_t my_ps_update = NULL; static db_ps_t my_ps_insert = NULL; static db_ps_t my_ps_update_vp = NULL; int index; db_val_t values[DIALOG_TABLE_TOTAL_COL_NO]; struct dlg_entry entry; struct dlg_cell * cell; unsigned char on_shutdown; int callee_leg,ins_done=0; static query_list_t *ins_list = NULL; db_key_t insert_keys[DIALOG_TABLE_TOTAL_COL_NO] = { &h_entry_column, &h_id_column, &call_id_column, &from_uri_column, &from_tag_column, &to_uri_column, &to_tag_column, &from_sock_column, &to_sock_column, &start_time_column, &from_route_column, &to_route_column, &from_contact_column, &to_contact_column, &mangled_fu_column, &mangled_tu_column, /*update chunk */ &state_column, &timeout_column, &from_cseq_column, &to_cseq_column, &from_ping_cseq_column, &to_ping_cseq_column, &vars_column, &profiles_column, &sflags_column, &flags_column}; if (dialog_db_handle==0 || use_dialog_table()!=0) return; on_shutdown = (ticks==0); /*save the current dialogs information*/ VAL_TYPE(values) = VAL_TYPE(values+1) = VAL_TYPE(values+9) = VAL_TYPE(values+16) = VAL_TYPE(values+17) = VAL_TYPE(values+20) = VAL_TYPE(values+21) = VAL_TYPE(values+24) = VAL_TYPE(values+25)= DB_INT; VAL_TYPE(values+2) = VAL_TYPE(values+3) = VAL_TYPE(values+4) = VAL_TYPE(values+5) = VAL_TYPE(values+6) = VAL_TYPE(values+7) = VAL_TYPE(values+8) = VAL_TYPE(values+10) = VAL_TYPE(values+11) = VAL_TYPE(values+12) = VAL_TYPE(values+13) = VAL_TYPE(values+14) = VAL_TYPE(values+15) = VAL_TYPE(values+18) = VAL_TYPE(values+19) = VAL_TYPE(values+22) = VAL_TYPE(values+23) = DB_STR; for(index = 0; index< d_table->size; index++){ /* lock the whole entry */ entry = (d_table->entries)[index]; dlg_lock( d_table, &entry); for(cell = entry.first; cell != NULL; cell = cell->next){ callee_leg = callee_idx(cell); if( (cell->flags & DLG_FLAG_NEW) != 0 ) { if ( cell->state == DLG_STATE_DELETED ) { /* don't need to insert dialogs already terminated */ continue; } LM_DBG("inserting new dialog %p\n",cell); SET_INT_VALUE(values, cell->h_entry); SET_INT_VALUE(values+1, cell->h_id); SET_STR_VALUE(values+2, cell->callid); SET_STR_VALUE(values+3, cell->from_uri); SET_STR_VALUE(values+4, cell->legs[DLG_CALLER_LEG].tag); SET_STR_VALUE(values+5, cell->to_uri); SET_STR_VALUE(values+6, cell->legs[callee_leg].tag); SET_STR_VALUE(values+7, cell->legs[DLG_CALLER_LEG].bind_addr->sock_str); if (cell->legs[callee_leg].bind_addr) { SET_STR_VALUE(values+8, cell->legs[callee_leg].bind_addr->sock_str); } else { VAL_NULL(values+8) = 1; } SET_INT_VALUE(values+9, cell->start_ts); SET_STR_VALUE(values+10, cell->legs[DLG_CALLER_LEG].route_set); SET_STR_VALUE(values+11, cell->legs[callee_leg].route_set); SET_STR_VALUE(values+12, cell->legs[DLG_CALLER_LEG].contact); SET_STR_VALUE(values+13, cell->legs[callee_leg].contact); SET_STR_VALUE(values+14,cell->legs[callee_leg].from_uri); SET_STR_VALUE(values+15,cell->legs[callee_leg].to_uri); SET_INT_VALUE(values+16, cell->state); SET_INT_VALUE(values+17, (unsigned int)((unsigned int)time(0) + cell->tl.timeout - get_ticks()) ); SET_STR_VALUE(values+18, cell->legs[DLG_CALLER_LEG].r_cseq); SET_STR_VALUE(values+19, cell->legs[callee_leg].r_cseq); SET_INT_VALUE(values+20, cell->legs[DLG_CALLER_LEG].last_gen_cseq); SET_INT_VALUE(values+21, cell->legs[callee_leg].last_gen_cseq); set_final_update_cols(values+22, cell, on_shutdown); SET_INT_VALUE(values+25, cell->flags & ~(DLG_FLAG_NEW|DLG_FLAG_CHANGED|DLG_FLAG_VP_CHANGED)); CON_PS_REFERENCE(dialog_db_handle) = &my_ps_insert; if (con_set_inslist(&dialog_dbf,dialog_db_handle, &ins_list,insert_keys,DIALOG_TABLE_TOTAL_COL_NO) < 0 ) CON_RESET_INSLIST(dialog_db_handle); if((dialog_dbf.insert(dialog_db_handle, insert_keys, values, DIALOG_TABLE_TOTAL_COL_NO)) !=0){ LM_ERR("could not add another dialog to db\n"); goto error; } if (ins_done==0) ins_done=1; /* dialog saved */ run_dlg_callbacks( DLGCB_SAVED, cell, 0, DLG_DIR_NONE, 0); cell->flags &= ~(DLG_FLAG_NEW |DLG_FLAG_CHANGED|DLG_FLAG_VP_CHANGED); } else if ( (cell->flags & DLG_FLAG_CHANGED)!=0 || on_shutdown ){ LM_DBG("updating existing dialog %p\n",cell); SET_INT_VALUE(values, cell->h_entry); SET_INT_VALUE(values+1, cell->h_id); SET_INT_VALUE(values+16, cell->state); SET_INT_VALUE(values+17, (unsigned int)((unsigned int)time(0) + cell->tl.timeout - get_ticks()) ); SET_STR_VALUE(values+18, cell->legs[DLG_CALLER_LEG].r_cseq); SET_STR_VALUE(values+19, cell->legs[callee_leg].r_cseq); SET_INT_VALUE(values+20, cell->legs[DLG_CALLER_LEG].last_gen_cseq); SET_INT_VALUE(values+21, cell->legs[callee_leg].last_gen_cseq); set_final_update_cols(values+22, cell, 1); SET_INT_VALUE(values+25, cell->flags); CON_PS_REFERENCE(dialog_db_handle) = &my_ps_update; if((dialog_dbf.update(dialog_db_handle, (insert_keys), 0, (values), (insert_keys+16), (values+16), 2, 10)) !=0) { LM_ERR("could not update database info\n"); goto error; } /* dialog saved */ run_dlg_callbacks( DLGCB_SAVED, cell, 0, DLG_DIR_NONE, 0); cell->flags &= ~(DLG_FLAG_CHANGED|DLG_FLAG_VP_CHANGED); } else if (cell->flags & DLG_FLAG_VP_CHANGED) { SET_INT_VALUE(values, cell->h_entry); SET_INT_VALUE(values+1, cell->h_id); set_final_update_cols(values+22, cell, 0); CON_PS_REFERENCE(dialog_db_handle) = &my_ps_update_vp; if((dialog_dbf.update(dialog_db_handle, (insert_keys), 0, (values), (insert_keys+22), (values+22), 2, 3)) !=0) { LM_ERR("could not update database info\n"); goto error; } run_dlg_callbacks( DLGCB_SAVED, cell, 0, DLG_DIR_NONE, 0); cell->flags &= ~DLG_FLAG_VP_CHANGED; } } dlg_unlock( d_table, &entry); } if (ins_done) { LM_DBG("dlg timer attempting to flush rows to DB\n"); /* flush everything to DB * so that next-time timer fires * we are sure that DB updates will be succesful */ if (ql_flush_rows(&dialog_dbf,dialog_db_handle,ins_list) < 0) LM_ERR("failed to flush rows to DB\n"); } return; error: dlg_unlock( d_table, &entry); }
/** * Does not copy strings */ int bdb_str2val(db_type_t _t, db_val_t* _v, char* _s, int _l) { static str dummy_string = {"", 0}; if(!_s) { memset(_v, 0, sizeof(db_val_t)); /* Initialize the string pointers to a dummy empty * string so that we do not crash when the NULL flag * is set but the module does not check it properly */ VAL_STRING(_v) = dummy_string.s; VAL_STR(_v) = dummy_string; VAL_BLOB(_v) = dummy_string; VAL_TYPE(_v) = _t; VAL_NULL(_v) = 1; return 0; } VAL_NULL(_v) = 0; switch(_t) { case DB_INT: if (db_str2int(_s, &VAL_INT(_v)) < 0) { LM_ERR("Error while converting INT value from string\n"); return -2; } else { VAL_TYPE(_v) = DB_INT; return 0; } break; case DB_BIGINT: if (db_str2bigint(_s, &VAL_BIGINT(_v)) < 0) { LM_ERR("Error while converting BIGINT value from string\n"); return -2; } else { VAL_TYPE(_v) = DB_BIGINT; return 0; } break; case DB_BITMAP: if (db_str2int(_s, &VAL_INT(_v)) < 0) { LM_ERR("Error while converting BITMAP value from string\n"); return -3; } else { VAL_TYPE(_v) = DB_BITMAP; return 0; } break; case DB_DOUBLE: if (db_str2double(_s, &VAL_DOUBLE(_v)) < 0) { LM_ERR("Error while converting DOUBLE value from string\n"); return -4; } else { VAL_TYPE(_v) = DB_DOUBLE; return 0; } break; case DB_STRING: if( strlen(_s)==4 && !strncasecmp(_s, "NULL", 4) ) VAL_NULL(_v) = 1; else { VAL_STRING(_v) = _s; VAL_TYPE(_v) = DB_STRING; VAL_FREE(_v) = 1; } return 0; case DB_STR: if( strlen(_s)==4 && !strncasecmp(_s, "NULL", 4) ) VAL_NULL(_v) = 1; else { VAL_STR(_v).s = (char*)_s; VAL_STR(_v).len = _l; VAL_TYPE(_v) = DB_STR; VAL_FREE(_v) = 1; } return 0; case DB_DATETIME: if( *_s == '\'') _s++; if (db_str2time(_s, &VAL_TIME(_v)) < 0) { LM_ERR("Error converting datetime\n"); return -5; } else { VAL_TYPE(_v) = DB_DATETIME; return 0; } break; case DB_BLOB: VAL_BLOB(_v).s = _s; VAL_BLOB(_v).len = _l; VAL_TYPE(_v) = DB_BLOB; VAL_FREE(_v) = 1; LM_DBG("got blob len %d\n", _l); return 0; } return -6; }
/* * Reload domain table to new hash table and when done, make new hash table * current one. */ int reload_tables ( void ) { db_key_t cols[4]; db1_res_t* res = NULL; db_row_t* row; struct domain_list **new_hash_table; int i; short type; str did, domain, name, value; int_str val; /* Choose new hash table and free its old contents */ if (*hash_table == hash_table_1) { hash_table_free(hash_table_2); new_hash_table = hash_table_2; } else { hash_table_free(hash_table_1); new_hash_table = hash_table_1; } cols[0] = &did_col; cols[1] = &name_col; cols[2] = &type_col; cols[3] = &value_col; if (domain_db_init(&d_db_url) < 0) { LM_ERR("unable to open database connection\n"); return -1; } if (domain_dbf.use_table(db_handle, &domain_attrs_table) < 0) { LM_ERR("error while trying to use domain_attrs table\n"); goto err; } if (domain_dbf.query(db_handle, NULL, 0, NULL, cols, 0, 4, 0, &res) < 0) { LM_ERR("error while querying database\n"); goto err; } row = RES_ROWS(res); LM_DBG("number of rows in domain_attrs table: %d\n", RES_ROW_N(res)); for (i = 0; i < RES_ROW_N(res); i++) { row = RES_ROWS(res) + i; if ((VAL_NULL(ROW_VALUES(row)) == 1) || (VAL_TYPE(ROW_VALUES(row)) != DB1_STRING)) { LM_ERR("did at row <%u> is null or not string\n", i); goto err; } did.s = (char *)VAL_STRING(ROW_VALUES(row)); did.len = strlen(did.s); if (did.len == 0) { LM_ERR("did at row <%u> is empty string\n", i); goto err; } if ((VAL_NULL(ROW_VALUES(row) + 1) == 1) || (VAL_TYPE(ROW_VALUES(row) + 1) != DB1_STRING)) { LM_ERR("name at row <%u> is null or not string\n", i); goto err; } name.s = (char *)VAL_STRING(ROW_VALUES(row) + 1); name.len = strlen(name.s); if (name.len == 0) { LM_ERR("name at row <%u> is empty string\n", i); goto err; } if ((VAL_NULL(ROW_VALUES(row) + 2) == 1) || ((VAL_TYPE(ROW_VALUES(row) + 2) != DB1_INT) && (VAL_TYPE(ROW_VALUES(row) + 2) != DB1_BIGINT))) { LM_ERR("type at row <%u> is null or not int\n", i); goto err; } if(VAL_TYPE(ROW_VALUES(row) + 2) == DB1_BIGINT) { type = (int)VAL_BIGINT(ROW_VALUES(row) + 2); } else { type = (int)VAL_INT(ROW_VALUES(row) + 2); } if ((type != 0) && (type != 2)) { LM_ERR("unknown type <%d> at row <%u>\n", type, i); goto err; } if ((VAL_NULL(ROW_VALUES(row) + 3) == 1) || (VAL_TYPE(ROW_VALUES(row) + 3) != DB1_STRING)) { LM_ERR("value at row <%u> is null or not string\n", i); goto err; } value.s = (char *)VAL_STRING(ROW_VALUES(row) + 3); value.len = strlen(value.s); if (type == 0) { if (str2sint(&value, &(val.n)) == -1) { LM_ERR("value at row <%u> is invalid int\n", i); goto err; } } else { val.s = value; } if (type == 0) LM_DBG("inserting <did/name/type/value> = <%s/%s/%d/%d> into attribute list\n", did.s, name.s, type, val.n); else LM_DBG("inserting <did/name/type/value> = <%s/%s/%d/%s> into attribute list\n", did.s, name.s, type, val.s.s); if (hash_table_attr_install(new_hash_table, &did, &name, type, &val) == -1) { LM_ERR("could not install attribute into hash table\n"); goto err; } } domain_dbf.free_result(db_handle, res); res = NULL; cols[0] = &domain_col; cols[1] = &did_col; if (domain_dbf.use_table(db_handle, &domain_table) < 0) { LM_ERR("error while trying to use domain table\n"); goto err; } if (domain_dbf.query(db_handle, NULL, 0, NULL, cols, 0, 2, 0, &res) < 0) { LM_ERR("error while querying database\n"); goto err; } row = RES_ROWS(res); LM_DBG("number of rows in domain table: %d\n", RES_ROW_N(res)); for (i = 0; i < RES_ROW_N(res); i++) { row = RES_ROWS(res) + i; if ((VAL_NULL(ROW_VALUES(row)) == 1) || (VAL_TYPE(ROW_VALUES(row)) != DB1_STRING)) { LM_ERR("domain at row <%u> is null or not string\n", i); goto err; } domain.s = (char *)VAL_STRING(ROW_VALUES(row)); domain.len = strlen(domain.s); if (domain.len == 0) { LM_ERR("domain at row <%u> is empty string\n", i); goto err; } if ((VAL_NULL(ROW_VALUES(row) + 1) != 1) && (VAL_TYPE(ROW_VALUES(row) + 1) != DB1_STRING)) { LM_ERR("did at row <%u> is not null or string\n", i); goto err; } if (VAL_NULL(ROW_VALUES(row) + 1) == 1) { did.s = domain.s; did.len = domain.len; } else { did.s = (char *)VAL_STRING(ROW_VALUES(row) + 1); did.len = strlen(did.s); if (did.len == 0) { LM_ERR("did at row <%u> is empty string\n", i); goto err; } } LM_DBG("inserting <did/domain> = <%s/%s> into hash table\n", did.s, domain.s); if (hash_table_install(new_hash_table, &did, &domain) == -1) { LM_ERR("could not install domain into hash table\n"); domain_dbf.free_result(db_handle, res); goto err; } } domain_dbf.free_result(db_handle, res); res = NULL; *hash_table = new_hash_table; domain_db_close(); return 1; err: domain_dbf.free_result(db_handle, res); res = NULL; domain_db_close(); return -1; }
/* * Used when converting result from a query */ int bdb_val2str(db_val_t* _v, char* _s, int* _len) { int l; if (VAL_NULL(_v)) { *_len = snprintf(_s, *_len, "NULL"); return 0; } switch(VAL_TYPE(_v)) { case DB_INT: if (db_int2str(VAL_INT(_v), _s, _len) < 0) { LM_ERR("Error while converting int to string\n"); return -2; } else { LM_DBG("Converted int to string\n"); return 0; } break; case DB_BIGINT: if (db_bigint2str(VAL_BIGINT(_v), _s, _len) < 0) { LM_ERR("Error while converting bigint to string\n"); return -2; } else { LM_DBG("Converted bigint to string\n"); return 0; } break; case DB_BITMAP: if (db_int2str(VAL_INT(_v), _s, _len) < 0) { LM_ERR("Error while converting bitmap to string\n"); return -3; } else { LM_DBG("Converted bitmap to string\n"); return 0; } break; case DB_DOUBLE: if (db_double2str(VAL_DOUBLE(_v), _s, _len) < 0) { LM_ERR("Error while converting double to string\n"); return -3; } else { LM_DBG("Converted double to string\n"); return 0; } break; case DB_STRING: l = strlen(VAL_STRING(_v)); if (*_len < l ) { LM_ERR("Destination buffer too short for string\n"); return -4; } else { LM_DBG("Converted string to string\n"); strncpy(_s, VAL_STRING(_v) , l); _s[l] = 0; *_len = l+1; /* count the 0 also */ return 0; } break; case DB_STR: l = VAL_STR(_v).len; if (*_len < l) { LM_ERR("Destination buffer too short for str\n"); return -5; } else { LM_DBG("Converted str to string\n"); strncpy(_s, VAL_STR(_v).s , l); *_len = l; return 0; } break; case DB_DATETIME: if (bdb_time2str(VAL_TIME(_v), _s, _len) < 0) { LM_ERR("Error while converting time_t to string\n"); return -6; } else { LM_DBG("Converted time_t to string\n"); return 0; } break; case DB_BLOB: l = VAL_BLOB(_v).len; if (*_len < l) { LM_ERR("Destination buffer too short for blob\n"); return -7; } else { strncpy(_s, VAL_BLOB(_v).s , l); LM_DBG("Converting BLOB [%.*s]\n", l,_s); *_len = l; return 0; } break; default: LM_DBG("Unknown data type\n"); return -8; } }
/*! * \brief Get all contacts from the database, in partitions if wanted * \see get_all_ucontacts * \param buf target buffer * \param len length of buffer * \param flags contact flags * \param part_idx part index * \param part_max maximal part * \param GAU options * \return 0 on success, positive if buffer size was not sufficient, negative on failure */ static inline int get_all_db_ucontacts(void *buf, int len, unsigned int flags, unsigned int part_idx, unsigned int part_max, int options) { struct socket_info *sock; unsigned int dbflags; db1_res_t* res = NULL; db_row_t *row; dlist_t *dom; str now; char now_s[25]; int port, proto; char *p; str addr; str recv; str path; str ruid; str host; unsigned int aorhash; int i; void *cp; int shortage, needed; db_key_t keys1[4]; /* where */ db_val_t vals1[4]; db_op_t ops1[4]; db_key_t keys2[6]; /* select */ int n[2] = {2,6}; /* number of dynamic values used on key1/key2 */ cp = buf; shortage = 0; /* Reserve space for terminating 0000 */ len -= sizeof(addr.len); /* get the current time in DB format */ now.len = 25; now.s = now_s; if (db_time2str( time(0), now.s, &now.len)!=0) { LM_ERR("failed to print now time\n"); return -1; } aorhash = 0; /* select fields */ keys2[0] = &received_col; keys2[1] = &contact_col; keys2[2] = &sock_col; keys2[3] = &cflags_col; keys2[4] = &path_col; keys2[5] = &ruid_col; /* where fields */ keys1[0] = &expires_col; ops1[0] = OP_GT; vals1[0].type = DB1_STR; vals1[0].nul = 0; vals1[0].val.str_val = now; keys1[1] = &partition_col; ops1[1] = OP_EQ; vals1[1].type = DB1_INT; vals1[1].nul = 0; if(_ul_max_partition>0) vals1[1].val.int_val = part_idx; else vals1[1].val.int_val = 0; if (flags & nat_bflag) { keys1[n[0]] = &keepalive_col; ops1[n[0]] = OP_EQ; vals1[n[0]].type = DB1_INT; vals1[n[0]].nul = 0; vals1[n[0]].val.int_val = 1; n[0]++; } if(options&GAU_OPT_SERVER_ID) { keys1[n[0]] = &srv_id_col; ops1[n[0]] = OP_EQ; vals1[n[0]].type = DB1_INT; vals1[n[0]].nul = 0; vals1[n[0]].val.int_val = server_id; n[0]++; } /* TODO: use part_idx and part_max on keys1 */ for (dom = root; dom!=NULL ; dom=dom->next) { if (ul_dbf.use_table(ul_dbh, dom->d->name) < 0) { LM_ERR("sql use_table failed\n"); return -1; } if (ul_dbf.query(ul_dbh, keys1, ops1, vals1, keys2, n[0], n[1], NULL, &res) <0 ) { LM_ERR("query error\n"); return -1; } if( RES_ROW_N(res)==0 ) { ul_dbf.free_result(ul_dbh, res); continue; } for(i = 0; i < RES_ROW_N(res); i++) { row = RES_ROWS(res) + i; /* received */ recv.s = (char*)VAL_STRING(ROW_VALUES(row)); if ( VAL_NULL(ROW_VALUES(row)) || recv.s==0 || recv.s[0]==0 ) { recv.s = NULL; recv.len = 0; } else { recv.len = strlen(recv.s); } /* contact */ addr.s = (char*)VAL_STRING(ROW_VALUES(row)+1); if (VAL_NULL(ROW_VALUES(row)+1) || addr.s==0 || addr.s[0]==0) { LM_ERR("empty contact -> skipping\n"); continue; } else { addr.len = strlen(addr.s); } /* path */ path.s = (char*)VAL_STRING(ROW_VALUES(row)+4); if (VAL_NULL(ROW_VALUES(row)+4) || path.s==0 || path.s[0]==0){ path.s = NULL; path.len = 0; } else { path.len = strlen(path.s); } /* ruid */ ruid.s = (char*)VAL_STRING(ROW_VALUES(row)+5); if (VAL_NULL(ROW_VALUES(row)+5) || ruid.s==0 || ruid.s[0]==0){ ruid.s = NULL; ruid.len = 0; } else { ruid.len = strlen(ruid.s); } needed = (int)(sizeof(addr.len) + addr.len + sizeof(recv.len) + recv.len + sizeof(sock) + sizeof(dbflags) + sizeof(path.len) + path.len + sizeof(ruid.len) + ruid.len + sizeof(aorhash)); if (len < needed) { shortage += needed ; continue; } /* write contact */ memcpy(cp, &addr.len, sizeof(addr.len)); cp = (char*)cp + sizeof(addr.len); memcpy(cp, addr.s, addr.len); cp = (char*)cp + addr.len; /* write received */ memcpy(cp, &recv.len, sizeof(recv.len)); cp = (char*)cp + sizeof(recv.len); /* copy received only if exist */ if(recv.len){ memcpy(cp, recv.s, recv.len); cp = (char*)cp + recv.len; } /* sock */ p = (char*)VAL_STRING(ROW_VALUES(row) + 2); if (VAL_NULL(ROW_VALUES(row)+2) || p==0 || p[0]==0){ sock = 0; } else { if (parse_phostport( p, &host.s, &host.len, &port, &proto)!=0) { LM_ERR("bad socket <%s>...set to 0\n", p); sock = 0; } else { sock = grep_sock_info( &host, (unsigned short)port, proto); if (sock==0) { LM_DBG("non-local socket <%s>...set to 0\n", p); } } } /* flags */ dbflags = VAL_BITMAP(ROW_VALUES(row) + 3); /* write sock and flags */ memcpy(cp, &sock, sizeof(sock)); cp = (char*)cp + sizeof(sock); memcpy(cp, &dbflags, sizeof(dbflags)); cp = (char*)cp + sizeof(dbflags); /* write path */ memcpy(cp, &path.len, sizeof(path.len)); cp = (char*)cp + sizeof(path.len); /* copy path only if exist */ if(path.len){ memcpy(cp, path.s, path.len); cp = (char*)cp + path.len; } /* write ruid */ memcpy(cp, &ruid.len, sizeof(ruid.len)); cp = (char*)cp + sizeof(ruid.len); /* copy ruid only if exist */ if(ruid.len){ memcpy(cp, ruid.s, ruid.len); cp = (char*)cp + ruid.len; } /* aorhash not used for db-only records, but it is added * (as 0) to match the struct used for mem records */ memcpy(cp, &aorhash, sizeof(aorhash)); cp = (char*)cp + sizeof(aorhash); len -= needed; } /* row cycle */ ul_dbf.free_result(ul_dbh, res); } /* domain cycle */ /* len < 0 is possible, if size of the buffer < sizeof(c->c.len) */ if (len >= 0) memset(cp, 0, sizeof(addr.len)); /* Shouldn't happen */ if (shortage > 0 && len > shortage) { abort(); } shortage -= len; return shortage > 0 ? shortage : 0; }
/* * Reload addr table to new hash table and when done, make new hash table * current one. */ int reload_address_table(void) { db_key_t cols[5]; db1_res_t* res = NULL; db_row_t* row; db_val_t* val; struct addr_list **new_hash_table; struct subnet *new_subnet_table; struct domain_name_list **new_domain_name_table; int i; unsigned int gid; unsigned int port; unsigned int mask; str ips; ip_addr_t *ipa; char *tagv; cols[0] = &grp_col; cols[1] = &ip_addr_col; cols[2] = &mask_col; cols[3] = &port_col; cols[4] = &tag_col; if (perm_dbf.use_table(db_handle, &address_table) < 0) { LM_ERR("failed to use table\n"); return -1; } if (perm_dbf.query(db_handle, NULL, 0, NULL, cols, 0, 5, 0, &res) < 0) { LM_ERR("failed to query database\n"); return -1; } /* Choose new hash table and free its old contents */ if (*addr_hash_table == addr_hash_table_1) { empty_addr_hash_table(addr_hash_table_2); new_hash_table = addr_hash_table_2; } else { empty_addr_hash_table(addr_hash_table_1); new_hash_table = addr_hash_table_1; } /* Choose new subnet table */ if (*subnet_table == subnet_table_1) { empty_subnet_table(subnet_table_2); new_subnet_table = subnet_table_2; } else { empty_subnet_table(subnet_table_1); new_subnet_table = subnet_table_1; } /* Choose new domain name table */ if (*domain_list_table == domain_list_table_1) { empty_domain_name_table(domain_list_table_2); new_domain_name_table = domain_list_table_2; } else { empty_domain_name_table(domain_list_table_1); new_domain_name_table = domain_list_table_1; } row = RES_ROWS(res); LM_DBG("Number of rows in address table: %d\n", RES_ROW_N(res)); for (i = 0; i < RES_ROW_N(res); i++) { val = ROW_VALUES(row + i); /* basic checks to db values */ if (ROW_N(row + i) != 5) { LM_DBG("failure during checks of db address table: Colums %d - expected 5\n", ROW_N(row + i)); goto dberror; } if ((VAL_TYPE(val) != DB1_INT) || VAL_NULL(val) || (VAL_INT(val) <= 0)) { LM_DBG("failure during checks of database value 1 (group) in address table\n"); goto dberror; } if ((VAL_TYPE(val + 1) != DB1_STRING) && (VAL_TYPE(val + 1) != DB1_STR)) { LM_DBG("failure during checks of database value 2 (IP address) in address table - not a string value\n"); goto dberror; } if (VAL_NULL(val + 1)) { LM_DBG("failure during checks of database value 2 (IP address) in address table - NULL value not permitted\n"); goto dberror; } if ((VAL_TYPE(val + 2) != DB1_INT) || VAL_NULL(val + 2)) { LM_DBG("failure during checks of database value 3 (subnet size/CIDR) in address table\n"); goto dberror; } if ((VAL_TYPE(val + 3) != DB1_INT) || VAL_NULL(val + 3)) { LM_DBG("failure during checks of database value 4 (port) in address table\n"); goto dberror; } gid = VAL_UINT(val); ips.s = (char *)VAL_STRING(val + 1); ips.len = strlen(ips.s); mask = VAL_UINT(val + 2); port = VAL_UINT(val + 3); tagv = VAL_NULL(val + 4)?NULL:(char *)VAL_STRING(val + 4); ipa = strtoipX(&ips); if ( ipa==NULL ) { LM_DBG("Domain name: %.*s\n", ips.len, ips.s); // goto dberror; } else { if(ipa->af == AF_INET6) { if((int)mask<0 || mask>128) { LM_DBG("failure during IP mask check for v6\n"); goto dberror; } } else { if((int)mask<0 || mask>32) { LM_DBG("failure during IP mask check for v4\n"); goto dberror; } } } if ( ipa ) { if ( (ipa->af==AF_INET6 && mask==128) || (ipa->af==AF_INET && mask==32) ) { if (addr_hash_table_insert(new_hash_table, gid, ipa, port, tagv) == -1) { LM_ERR("hash table problem\n"); perm_dbf.free_result(db_handle, res); return -1; } LM_DBG("Tuple <%u, %s, %u> inserted into address hash table\n", gid, ips.s, port); } else { if (subnet_table_insert(new_subnet_table, gid, ipa, mask, port, tagv) == -1) { LM_ERR("subnet table problem\n"); perm_dbf.free_result(db_handle, res); return -1; } LM_DBG("Tuple <%u, %s, %u, %u> inserted into subnet table\n", gid, ips.s, port, mask); } } else { if (domain_name_table_insert(new_domain_name_table, gid, &ips, port, tagv) == -1) { LM_ERR("domain name table problem\n"); perm_dbf.free_result(db_handle, res); return -1; } LM_DBG("Tuple <%u, %s, %u> inserted into domain name table\n", gid, ips.s, port); } } perm_dbf.free_result(db_handle, res); *addr_hash_table = new_hash_table; *subnet_table = new_subnet_table; *domain_list_table = new_domain_name_table; LM_DBG("address table reloaded successfully.\n"); return 1; dberror: LM_ERR("database problem - invalid record\n"); perm_dbf.free_result(db_handle, res); return -1; }
/* * Check if username in specified header field is in a table */ int db_is_user_in(struct sip_msg* _msg, char* _hf, char* _grp) { static db_ps_t my_ps = NULL; db_key_t keys[3]; db_val_t vals[3]; db_key_t col[1]; db_res_t* res = NULL; keys[0] = &user_column; keys[1] = &group_column; keys[2] = &domain_column; col[0] = &group_column; str hf_s = { NULL, 0 }; str grp_s = { NULL, 0 }; if(_hf == NULL || fixup_get_svalue(_msg, (gparam_p)_hf, &hf_s) != 0) { LM_ERR("Invalid parameter URI\n"); return -1; } if(_grp == NULL || fixup_get_svalue(_msg, (gparam_p)_grp, &grp_s) != 0) { LM_ERR("Invalid parameter grp\n"); return -1; } if ( get_username_domain( _msg, &hf_s, &(VAL_STR(vals)), &(VAL_STR(vals+2)))!=0) { LM_ERR("failed to get username@domain\n"); return -1; } if (VAL_STR(vals).s==NULL || VAL_STR(vals).len==0 ) { LM_DBG("no username part\n"); return -1; } VAL_TYPE(vals) = VAL_TYPE(vals + 1) = VAL_TYPE(vals + 2) = DB_STR; VAL_NULL(vals) = VAL_NULL(vals + 1) = VAL_NULL(vals + 2) = 0; VAL_STR(vals + 1) = *(&grp_s); group_dbf.use_table(group_dbh, &table); CON_PS_REFERENCE(group_dbh) = &my_ps; if (group_dbf.query(group_dbh, keys, 0, vals, col, (use_domain) ? (3): (2), 1, 0, &res) < 0) { LM_ERR("failed to query database\n"); return -5; } if (RES_ROW_N(res) == 0) { LM_DBG("user is not in group '%.*s'\n", (grp_s.len), ZSW((grp_s.s))); group_dbf.free_result(group_dbh, res); return -6; } else { LM_DBG("user is in group '%.*s'\n", (grp_s.len), ZSW((grp_s.s))); group_dbf.free_result(group_dbh, res); return 1; } }
static int sync_dlg_db_mem(void) { db_res_t * res; db_val_t * values; db_row_t * rows; struct dlg_entry *d_entry; struct dlg_cell *it,*known_dlg,*dlg=NULL; int i, nr_rows,callee_leg_idx,next_id,db_timeout; int no_rows = 10; unsigned int db_caller_cseq,db_callee_cseq,dlg_caller_cseq,dlg_callee_cseq; struct socket_info *caller_sock,*callee_sock; str callid, from_uri, to_uri, from_tag, to_tag; str cseq1,cseq2,contact1,contact2,rroute1,rroute2,mangled_fu,mangled_tu; res = 0; if((nr_rows = select_entire_dialog_table(&res,&no_rows)) < 0) goto error; nr_rows = RES_ROW_N(res); do { LM_DBG("loading information from database for %i dialogs\n", nr_rows); rows = RES_ROWS(res); /* for every row---dialog */ for(i=0; i<nr_rows; i++){ values = ROW_VALUES(rows + i); if (VAL_NULL(values) || VAL_NULL(values+1)) { LM_ERR("columns %.*s or/and %.*s cannot be null -> skipping\n", h_entry_column.len, h_entry_column.s, h_id_column.len, h_id_column.s); continue; } if (VAL_NULL(values+7) || VAL_NULL(values+8)) { LM_ERR("columns %.*s or/and %.*s cannot be null -> skipping\n", start_time_column.len, start_time_column.s, state_column.len, state_column.s); continue; } if ( VAL_INT(values+8) == DLG_STATE_DELETED ) { LM_DBG("dialog already terminated -> skipping\n"); continue; } /*restore the dialog info*/ GET_STR_VALUE(callid, values, 2, 1, 0); GET_STR_VALUE(from_tag, values, 4, 1, 0); GET_STR_VALUE(to_tag, values, 6, 1, 1); /* TODO - check about hash resize ? maybe hash was lowered & we overflow the hash */ known_dlg = 0; d_entry = &(d_table->entries[VAL_INT(values)]); for (it=d_entry->first;it;it=it->next) if (it->callid.len == callid.len && it->legs[DLG_CALLER_LEG].tag.len == from_tag.len && memcmp(it->callid.s,callid.s,callid.len)==0 && memcmp(it->legs[DLG_CALLER_LEG].tag.s,from_tag.s,from_tag.len)==0) { /* callid & ftag match */ callee_leg_idx = callee_idx(it); if (it->legs[callee_leg_idx].tag.len == to_tag.len && memcmp(it->legs[callee_leg_idx].tag.s,to_tag.s,to_tag.len)==0) { /* full dlg match */ known_dlg = it; break; } } if (known_dlg == 0) { LM_DBG("First seen dialog - load all stuff - callid = [%.*s]\n",callid.len,callid.s); GET_STR_VALUE(from_uri, values, 3, 1, 0); GET_STR_VALUE(to_uri, values, 5, 1, 0); caller_sock = create_socket_info(values, 16); callee_sock = create_socket_info(values, 17); if (caller_sock == NULL || callee_sock == NULL) { LM_ERR("Dialog in DB doesn't match any listening sockets"); continue; } /* first time we see this dialog - build it from scratch */ if((dlg=build_new_dlg(&callid, &from_uri, &to_uri, &from_tag))==0){ LM_ERR("failed to build new dialog\n"); goto error; } if(dlg->h_entry != VAL_INT(values)){ LM_ERR("inconsistent hash data in the dialog database: " "you may have restarted opensips using a different " "hash_size: please erase %.*s database and restart\n", dialog_table_name.len, dialog_table_name.s); shm_free(dlg); goto error; } /*link the dialog*/ link_dlg(dlg, 0); dlg->h_id = VAL_INT(values+1); next_id = d_table->entries[dlg->h_entry].next_id; d_table->entries[dlg->h_entry].next_id = (next_id < dlg->h_id) ? (dlg->h_id+1) : next_id; dlg->start_ts = VAL_INT(values+7); dlg->state = VAL_INT(values+8); if (dlg->state==DLG_STATE_CONFIRMED_NA || dlg->state==DLG_STATE_CONFIRMED) { if_update_stat(dlg_enable_stats, active_dlgs, 1); } else if (dlg->state==DLG_STATE_EARLY) { if_update_stat(dlg_enable_stats, early_dlgs, 1); } GET_STR_VALUE(cseq1, values, 10 , 1, 1); GET_STR_VALUE(cseq2, values, 11 , 1, 1); GET_STR_VALUE(rroute1, values, 12, 0, 0); GET_STR_VALUE(rroute2, values, 13, 0, 0); GET_STR_VALUE(contact1, values, 14, 0, 1); GET_STR_VALUE(contact2, values, 15, 0, 1); GET_STR_VALUE(mangled_fu, values, 24,0,1); GET_STR_VALUE(mangled_tu, values, 25,0,1); /* add the 2 legs */ if ( (dlg_add_leg_info( dlg, &from_tag, &rroute1, &contact1, &cseq1, caller_sock,0,0)!=0) || (dlg_add_leg_info( dlg, &to_tag, &rroute2, &contact2, &cseq2, callee_sock,&mangled_fu,&mangled_tu)!=0) ) { LM_ERR("dlg_set_leg_info failed\n"); /* destroy the dialog */ unref_dlg(dlg,1); continue; } dlg->legs_no[DLG_LEG_200OK] = DLG_FIRST_CALLEE_LEG; /* script variables */ if (!VAL_NULL(values+18)) read_dialog_vars( VAL_STR(values+18).s, VAL_STR(values+18).len, dlg); /* profiles */ if (!VAL_NULL(values+19)) read_dialog_profiles( VAL_STR(values+19).s, strlen(VAL_STR(values+19).s), dlg,0); /* script flags */ if (!VAL_NULL(values+20)) { dlg->user_flags = VAL_INT(values+20); } /* top hiding */ dlg->flags = VAL_INT(values+23); if (dlg_db_mode==DB_MODE_SHUTDOWN) dlg->flags |= DLG_FLAG_NEW; /* calculcate timeout */ dlg->tl.timeout = (unsigned int)(VAL_INT(values+9)) + get_ticks(); if (dlg->tl.timeout<=(unsigned int)time(0)) dlg->tl.timeout = 0; else dlg->tl.timeout -= (unsigned int)time(0); /* restore the timer values */ if (0 != insert_dlg_timer( &(dlg->tl), (int)dlg->tl.timeout )) { LM_CRIT("Unable to insert dlg %p [%u:%u] " "with clid '%.*s' and tags '%.*s' '%.*s'\n", dlg, dlg->h_entry, dlg->h_id, dlg->callid.len, dlg->callid.s, dlg->legs[DLG_CALLER_LEG].tag.len, dlg->legs[DLG_CALLER_LEG].tag.s, dlg->legs[callee_idx(dlg)].tag.len, ZSW(dlg->legs[callee_idx(dlg)].tag.s)); /* destroy the dialog */ unref_dlg(dlg,1); continue; } /* reference the dialog as kept in the timer list */ ref_dlg(dlg,1); LM_DBG("current dialog timeout is %u\n", dlg->tl.timeout); dlg->lifetime = 0; dlg->legs[DLG_CALLER_LEG].last_gen_cseq = (unsigned int)(VAL_INT(values+21)); dlg->legs[callee_idx(dlg)].last_gen_cseq = (unsigned int)(VAL_INT(values+22)); if (dlg->flags & DLG_FLAG_PING_CALLER || dlg->flags & DLG_FLAG_PING_CALLEE) { if (0 != insert_ping_timer(dlg)) LM_CRIT("Unable to insert dlg %p into ping timer\n",dlg); else { /* reference dialog as kept in ping timer list */ ref_dlg(dlg,1); } } } else { /* we already saw this dialog before * check which is the newer version */ if (known_dlg->state > VAL_INT(values+8)) { LM_DBG("mem has a newer state - ignore \n"); /* we know a newer version compared to the DB * ignore it */ goto next_dialog; } else if (known_dlg->state == VAL_INT(values+8)) { LM_DBG("mem has same state as DB \n"); /* same state :-( no way to tell which is newer */ /* play nice and store longest timeout, although not always correct*/ db_timeout = (unsigned int)(VAL_INT(values+9)) + get_ticks(); if (db_timeout<=(unsigned int)time(0)) db_timeout = 0; else db_timeout -= (unsigned int)time(0); if (known_dlg->tl.timeout < db_timeout) known_dlg->tl.timeout = db_timeout; /* check with is newer cseq for caller leg */ if (!VAL_NULL(values+10)) { cseq1.s = VAL_STR(values+10).s; cseq1.len = strlen(cseq1.s); str2int(&cseq1,&db_caller_cseq); str2int(&known_dlg->legs[DLG_CALLER_LEG].r_cseq,&dlg_caller_cseq); /* Is DB cseq newer ? */ if (db_caller_cseq > dlg_caller_cseq) { if (known_dlg->legs[DLG_CALLER_LEG].r_cseq.len < cseq1.len) { known_dlg->legs[DLG_CALLER_LEG].r_cseq.s = shm_realloc(known_dlg->legs[DLG_CALLER_LEG].r_cseq.s,cseq1.len); if (!known_dlg->legs[DLG_CALLER_LEG].r_cseq.s) { LM_ERR("no more shm\n"); goto next_dialog; } } memcpy(known_dlg->legs[DLG_CALLER_LEG].r_cseq.s,cseq1.s,cseq1.len); known_dlg->legs[DLG_CALLER_LEG].r_cseq.len = cseq1.len; } } else { /* DB has a null cseq - just keep * what we have so far */ ; } /* check with is newer cseq for caller leg */ if (!VAL_NULL(values+11)) { cseq2.s = VAL_STR(values+11).s; cseq2.len = strlen(cseq2.s); callee_leg_idx = callee_idx(known_dlg); str2int(&cseq2,&db_callee_cseq); str2int(&known_dlg->legs[callee_leg_idx].r_cseq,&dlg_callee_cseq); /* Is DB cseq newer ? */ if (db_callee_cseq > dlg_callee_cseq) { if (known_dlg->legs[callee_leg_idx].r_cseq.len < cseq2.len) { known_dlg->legs[callee_leg_idx].r_cseq.s = shm_realloc(known_dlg->legs[callee_leg_idx].r_cseq.s,cseq2.len); if (!known_dlg->legs[callee_leg_idx].r_cseq.s) { LM_ERR("no more shm\n"); goto next_dialog; } } memcpy(known_dlg->legs[callee_leg_idx].r_cseq.s,cseq2.s,cseq2.len); known_dlg->legs[callee_leg_idx].r_cseq.len = cseq2.len; } } else { /* DB has a null cseq - just keep * what we have so far */ ; } /* update ping cseqs, whichever is newer */ if (known_dlg->legs[DLG_CALLER_LEG].last_gen_cseq < (unsigned int)(VAL_INT(values+21))) known_dlg->legs[DLG_CALLER_LEG].last_gen_cseq = (unsigned int)(VAL_INT(values+21)); if (known_dlg->legs[callee_idx(known_dlg)].last_gen_cseq < (unsigned int)(VAL_INT(values+22))) known_dlg->legs[callee_idx(known_dlg)].last_gen_cseq = (unsigned int)(VAL_INT(values+22)); /* update script variables * if already found, delete the old ones * and replace with new one */ if (!VAL_NULL(values+18)) read_dialog_vars( VAL_STR(values+18).s, VAL_STR(values+18).len, known_dlg); /* skip flags - keep what we have - anyway can't tell which is new */ /* profiles - do not insert into a profile * is dlg is already in that profile*/ if (!VAL_NULL(values+19)) read_dialog_profiles( VAL_STR(values+19).s, strlen(VAL_STR(values+19).s), known_dlg,1); } else { /* DB has newer state, just update fields from DB */ LM_DBG("DB has newer state \n"); /* set new state */ known_dlg->state = VAL_INT(values+8); /* update timeout */ known_dlg->tl.timeout = (unsigned int)(VAL_INT(values+9)) + get_ticks(); if (known_dlg->tl.timeout<=(unsigned int)time(0)) known_dlg->tl.timeout = 0; else known_dlg->tl.timeout -= (unsigned int)time(0); /* update cseqs */ if (!VAL_NULL(values+10)) { cseq1.s = VAL_STR(values+10).s; cseq1.len = strlen(cseq1.s); if (known_dlg->legs[DLG_CALLER_LEG].r_cseq.len < cseq1.len) { known_dlg->legs[DLG_CALLER_LEG].r_cseq.s = shm_realloc(known_dlg->legs[DLG_CALLER_LEG].r_cseq.s,cseq1.len); if (!known_dlg->legs[DLG_CALLER_LEG].r_cseq.s) { LM_ERR("no more shm\n"); goto next_dialog; } } memcpy(known_dlg->legs[DLG_CALLER_LEG].r_cseq.s,cseq1.s,cseq1.len); known_dlg->legs[DLG_CALLER_LEG].r_cseq.len = cseq1.len; } if (!VAL_NULL(values+11)) { cseq2.s = VAL_STR(values+11).s; cseq2.len = strlen(cseq1.s); callee_leg_idx = callee_idx(known_dlg); if (known_dlg->legs[callee_leg_idx].r_cseq.len < cseq2.len) { known_dlg->legs[callee_leg_idx].r_cseq.s = shm_realloc(known_dlg->legs[callee_leg_idx].r_cseq.s,cseq2.len); if (!known_dlg->legs[callee_leg_idx].r_cseq.s) { LM_ERR("no more shm\n"); goto next_dialog; } } memcpy(known_dlg->legs[callee_leg_idx].r_cseq.s,cseq2.s,cseq2.len); known_dlg->legs[callee_leg_idx].r_cseq.len = cseq2.len; } /* update ping cseqs */ known_dlg->legs[DLG_CALLER_LEG].last_gen_cseq = (unsigned int)(VAL_INT(values+21)); known_dlg->legs[callee_idx(known_dlg)].last_gen_cseq = (unsigned int)(VAL_INT(values+22)); /* update flags */ known_dlg->flags = VAL_INT(values+23); if (dlg_db_mode==DB_MODE_SHUTDOWN) known_dlg->flags |= DLG_FLAG_NEW; /* update script variables * if already found, delete the old one * and replace with new one */ if (!VAL_NULL(values+18)) read_dialog_vars( VAL_STR(values+18).s, VAL_STR(values+18).len, known_dlg); /* profiles - do not insert into a profile * is dlg is already in that profile*/ if (!VAL_NULL(values+19)) read_dialog_profiles( VAL_STR(values+19).s, strlen(VAL_STR(values+19).s), known_dlg,1); } } next_dialog: ; } /* any more data to be fetched ?*/ if (DB_CAPABILITY(dialog_dbf, DB_CAP_FETCH)) { if (dialog_dbf.fetch_result( dialog_db_handle, &res,no_rows) < 0) { LM_ERR("fetching more rows failed\n"); goto error; } nr_rows = RES_ROW_N(res); } else { nr_rows = 0; } }while (nr_rows>0); return 0; error: return -1; }
int uac_reg_load_db(void) { db1_con_t *reg_db_con = NULL; db_func_t reg_dbf; reg_uac_t reg; db_key_t db_cols[10] = { &l_uuid_column, &l_username_column, &l_domain_column, &r_username_column, &r_domain_column, &realm_column, &auth_username_column, &auth_password_column, &auth_proxy_column, &expires_column }; db1_res_t* db_res = NULL; int i, ret; /* binding to db module */ if(reg_db_url.s==NULL) { LM_ERR("no db url\n"); return -1; } if(db_bind_mod(®_db_url, ®_dbf)) { LM_ERR("database module not found\n"); return -1; } if (!DB_CAPABILITY(reg_dbf, DB_CAP_ALL)) { LM_ERR("database module does not " "implement all functions needed by the module\n"); return -1; } /* open a connection with the database */ reg_db_con = reg_dbf.init(®_db_url); if(reg_db_con==NULL) { LM_ERR("failed to connect to the database\n"); return -1; } if (reg_dbf.use_table(reg_db_con, ®_db_table) < 0) { LM_ERR("failed to use_table\n"); return -1; } if (DB_CAPABILITY(reg_dbf, DB_CAP_FETCH)) { if(reg_dbf.query(reg_db_con, 0, 0, 0, db_cols, 0, 10, 0, 0) < 0) { LM_ERR("Error while querying db\n"); return -1; } if(reg_dbf.fetch_result(reg_db_con, &db_res, reg_fetch_rows)<0) { LM_ERR("Error while fetching result\n"); if (db_res) reg_dbf.free_result(reg_db_con, db_res); goto error; } else { if(RES_ROW_N(db_res)==0) { goto done; } } } else { if((ret=reg_dbf.query(reg_db_con, NULL, NULL, NULL, db_cols, 0, 10, 0, &db_res))!=0 || RES_ROW_N(db_res)<=0 ) { reg_dbf.free_result(reg_db_con, db_res); if( ret==0) { return 0; } else { goto error; } } } do { for(i=0; i<RES_ROW_N(db_res); i++) { memset(®, 0, sizeof(reg_uac_t));; /* check for NULL values ?!?! */ reg_db_set_attr(l_uuid, 0); reg_db_set_attr(l_username, 1); reg_db_set_attr(l_domain, 2); reg_db_set_attr(r_username, 3); reg_db_set_attr(r_domain, 4); /* realm may be empty */ if(!VAL_NULL(&RES_ROWS(db_res)[i].values[5])) { reg.realm.s = (char*)(RES_ROWS(db_res)[i].values[5].val.string_val); reg.realm.len = strlen(reg.realm.s); } reg_db_set_attr(auth_username, 6); reg_db_set_attr(auth_password, 7); reg_db_set_attr(auth_proxy, 8); reg.expires = (unsigned int)RES_ROWS(db_res)[i].values[9].val.int_val; if(reg_ht_add(®)<0) { LM_ERR("Error adding reg to htable\n"); goto error; } } if (DB_CAPABILITY(reg_dbf, DB_CAP_FETCH)) { if(reg_dbf.fetch_result(reg_db_con, &db_res, reg_fetch_rows)<0) { LM_ERR("Error while fetching!\n"); if (db_res) reg_dbf.free_result(reg_db_con, db_res); goto error; } } else { break; } } while(RES_ROW_N(db_res)>0); reg_dbf.free_result(reg_db_con, db_res); reg_dbf.close(reg_db_con); done: return 0; error: if (reg_db_con) { reg_dbf.free_result(reg_db_con, db_res); reg_dbf.close(reg_db_con); } return -1; }
static int load_dialog_info_from_db(int dlg_hash_size) { db_res_t * res; db_val_t * values; db_row_t * rows; int i, nr_rows; struct dlg_cell *dlg; str callid, from_uri, to_uri, from_tag, to_tag; str cseq1,cseq2,contact1,contact2,rroute1,rroute2,mangled_fu,mangled_tu; unsigned int next_id; int no_rows = 10; struct socket_info *caller_sock,*callee_sock; res = 0; if((nr_rows = select_entire_dialog_table(&res,&no_rows)) < 0) goto end; nr_rows = RES_ROW_N(res); do { LM_DBG("loading information from database for %i dialogs\n", nr_rows); rows = RES_ROWS(res); /* for every row---dialog */ for(i=0; i<nr_rows; i++){ values = ROW_VALUES(rows + i); if (VAL_NULL(values) || VAL_NULL(values+1)) { LM_ERR("columns %.*s or/and %.*s cannot be null -> skipping\n", h_entry_column.len, h_entry_column.s, h_id_column.len, h_id_column.s); continue; } if (VAL_NULL(values+7) || VAL_NULL(values+8)) { LM_ERR("columns %.*s or/and %.*s cannot be null -> skipping\n", start_time_column.len, start_time_column.s, state_column.len, state_column.s); continue; } if ( VAL_INT(values+8) == DLG_STATE_DELETED ) { LM_DBG("dialog already terminated -> skipping\n"); continue; } caller_sock = create_socket_info(values, 16); callee_sock = create_socket_info(values, 17); if (caller_sock == NULL || callee_sock == NULL) { LM_ERR("Dialog in DB doesn't match any listening sockets"); continue; } /*restore the dialog info*/ GET_STR_VALUE(callid, values, 2, 1, 0); GET_STR_VALUE(from_uri, values, 3, 1, 0); GET_STR_VALUE(from_tag, values, 4, 1, 0); GET_STR_VALUE(to_uri, values, 5, 1, 0); if((dlg=build_new_dlg(&callid, &from_uri, &to_uri, &from_tag))==0){ LM_ERR("failed to build new dialog\n"); goto error; } if(dlg->h_entry != VAL_INT(values)){ LM_ERR("inconsistent hash data in the dialog database: " "you may have restarted opensips using a different " "hash_size: please erase %.*s database and restart\n", dialog_table_name.len, dialog_table_name.s); shm_free(dlg); goto error; } /*link the dialog*/ link_dlg(dlg, 0); dlg->h_id = VAL_INT(values+1); next_id = d_table->entries[dlg->h_entry].next_id; d_table->entries[dlg->h_entry].next_id = (next_id < dlg->h_id) ? (dlg->h_id+1) : next_id; GET_STR_VALUE(to_tag, values, 6, 1, 1); dlg->start_ts = VAL_INT(values+7); dlg->state = VAL_INT(values+8); if (dlg->state==DLG_STATE_CONFIRMED_NA || dlg->state==DLG_STATE_CONFIRMED) { active_dlgs_cnt++; } else if (dlg->state==DLG_STATE_EARLY) { early_dlgs_cnt++; } GET_STR_VALUE(cseq1, values, 10 , 1, 1); GET_STR_VALUE(cseq2, values, 11 , 1, 1); GET_STR_VALUE(rroute1, values, 12, 0, 0); GET_STR_VALUE(rroute2, values, 13, 0, 0); GET_STR_VALUE(contact1, values, 14, 0, 1); GET_STR_VALUE(contact2, values, 15, 0, 1); GET_STR_VALUE(mangled_fu, values, 24,0,1); GET_STR_VALUE(mangled_tu, values, 25,0,1); /* add the 2 legs */ if ( (dlg_add_leg_info( dlg, &from_tag, &rroute1, &contact1, &cseq1, caller_sock,0,0)!=0) || (dlg_add_leg_info( dlg, &to_tag, &rroute2, &contact2, &cseq2, callee_sock,&mangled_fu,&mangled_tu)!=0) ) { LM_ERR("dlg_set_leg_info failed\n"); /* destroy the dialog */ unref_dlg(dlg,1); continue; } dlg->legs_no[DLG_LEG_200OK] = DLG_FIRST_CALLEE_LEG; /* script variables */ if (!VAL_NULL(values+18)) read_dialog_vars( VAL_STR(values+18).s, VAL_STR(values+18).len, dlg); /* profiles */ if (!VAL_NULL(values+19)) read_dialog_profiles( VAL_STR(values+19).s, strlen(VAL_STR(values+19).s), dlg,0); /* script flags */ if (!VAL_NULL(values+20)) { dlg->user_flags = VAL_INT(values+20); } /* top hiding */ dlg->flags = VAL_INT(values+23); if (dlg_db_mode==DB_MODE_SHUTDOWN) dlg->flags |= DLG_FLAG_NEW; /* calculcate timeout */ dlg->tl.timeout = (unsigned int)(VAL_INT(values+9)) + get_ticks(); if (dlg->tl.timeout<=(unsigned int)time(0)) dlg->tl.timeout = 0; else dlg->tl.timeout -= (unsigned int)time(0); /* restore the timer values */ if (0 != insert_dlg_timer( &(dlg->tl), (int)dlg->tl.timeout )) { LM_CRIT("Unable to insert dlg %p [%u:%u] " "with clid '%.*s' and tags '%.*s' '%.*s'\n", dlg, dlg->h_entry, dlg->h_id, dlg->callid.len, dlg->callid.s, dlg->legs[DLG_CALLER_LEG].tag.len, dlg->legs[DLG_CALLER_LEG].tag.s, dlg->legs[callee_idx(dlg)].tag.len, ZSW(dlg->legs[callee_idx(dlg)].tag.s)); /* destroy the dialog */ unref_dlg(dlg,1); continue; } /* reference the dialog as kept in the timer list */ ref_dlg(dlg,1); LM_DBG("current dialog timeout is %u\n", dlg->tl.timeout); dlg->lifetime = 0; dlg->legs[DLG_CALLER_LEG].last_gen_cseq = (unsigned int)(VAL_INT(values+21)); dlg->legs[callee_idx(dlg)].last_gen_cseq = (unsigned int)(VAL_INT(values+22)); if (dlg->flags & DLG_FLAG_PING_CALLER || dlg->flags & DLG_FLAG_PING_CALLEE) { if (0 != insert_ping_timer(dlg)) LM_CRIT("Unable to insert dlg %p into ping timer\n",dlg); else { /* reference dialog as kept in ping timer list */ ref_dlg(dlg,1); } } next_dialog: ; } /* any more data to be fetched ?*/ if (DB_CAPABILITY(dialog_dbf, DB_CAP_FETCH)) { if (dialog_dbf.fetch_result( dialog_db_handle, &res,no_rows) < 0) { LM_ERR("fetching more rows failed\n"); goto error; } nr_rows = RES_ROW_N(res); } else { nr_rows = 0; } }while (nr_rows>0); end: dialog_dbf.free_result(dialog_db_handle, res); return 0; error: dialog_dbf.free_result(dialog_db_handle, res); return -1; }
/* * Release memory used by row */ inline int db_free_row(db_row_t* _r) { int col; db_val_t* _val; if (!_r) { LM_ERR("invalid parameter value\n"); return -1; } /* * Loop thru each columm, then check to determine if the storage pointed to * by db_val_t structure must be freed. This is required for all data types * which use a pointer to a buffer like DB1_STRING, DB1_STR and DB1_BLOB and * the database module copied them during the assignment. * If this is not done, a memory leak will happen. * Don't try to free the static dummy string (as indicated from the NULL value), * as this is not valid. */ for (col = 0; col < ROW_N(_r); col++) { _val = &(ROW_VALUES(_r)[col]); switch (VAL_TYPE(_val)) { case DB1_STRING: if ( (!VAL_NULL(_val)) && VAL_FREE(_val)) { LM_DBG("free VAL_STRING[%d] '%s' at %p\n", col, (char *)VAL_STRING(_val), (char *)VAL_STRING(_val)); pkg_free((char *)VAL_STRING(_val)); VAL_STRING(_val) = NULL; } break; case DB1_STR: if ( (!VAL_NULL(_val)) && VAL_FREE(_val)) { LM_DBG("free VAL_STR[%d] '%.*s' at %p\n", col, VAL_STR(_val).len, VAL_STR(_val).s, VAL_STR(_val).s); pkg_free(VAL_STR(_val).s); VAL_STR(_val).s = NULL; } break; case DB1_BLOB: if ( (!VAL_NULL(_val)) && VAL_FREE(_val)) { LM_DBG("free VAL_BLOB[%d] at %p\n", col, VAL_BLOB(_val).s); pkg_free(VAL_BLOB(_val).s); VAL_BLOB(_val).s = NULL; } break; default: break; } } /* now as we freed all, set number of colums to zero again */ ROW_N(_r) = 0; if (ROW_VALUES(_r)) { LM_DBG("freeing row values at %p\n", ROW_VALUES(_r)); pkg_free(ROW_VALUES(_r)); ROW_VALUES(_r) = NULL; } return 0; }
int update_dialog_dbinfo(struct dlg_cell * cell) { static db_ps_t my_ps_insert = NULL; static db_ps_t my_ps_update = NULL; static db_ps_t my_ps_update_vp = NULL; struct dlg_entry entry; db_val_t values[DIALOG_TABLE_TOTAL_COL_NO]; int callee_leg; db_key_t insert_keys[DIALOG_TABLE_TOTAL_COL_NO] = { &h_entry_column, &h_id_column, &call_id_column, &from_uri_column, &from_tag_column, &to_uri_column, &to_tag_column, &from_sock_column, &to_sock_column, &start_time_column, &mangled_fu_column, &mangled_tu_column, &state_column, &timeout_column, &from_cseq_column, &to_cseq_column, &from_ping_cseq_column, &to_ping_cseq_column,&flags_column, &vars_column, &profiles_column, &sflags_column, &from_route_column, &to_route_column, &from_contact_column,&to_contact_column}; if(use_dialog_table()!=0) return -1; callee_leg= callee_idx(cell); if((cell->flags & DLG_FLAG_NEW) != 0){ /* save all the current dialogs information*/ VAL_TYPE(values) = VAL_TYPE(values+1) = VAL_TYPE(values+9) = VAL_TYPE(values+12) = VAL_TYPE(values+13) = VAL_TYPE(values+16) = VAL_TYPE(values+17) = VAL_TYPE(values+18) = VAL_TYPE(values+21) = DB_INT; VAL_TYPE(values+2) = VAL_TYPE(values+3) = VAL_TYPE(values+4) = VAL_TYPE(values+5) = VAL_TYPE(values+6) = VAL_TYPE(values+7) = VAL_TYPE(values+8) = VAL_TYPE(values+10) = VAL_TYPE(values+11) = VAL_TYPE(values+14) = VAL_TYPE(values+15) = VAL_TYPE(values+19) = VAL_TYPE(values+20) = VAL_TYPE(values+22) = VAL_TYPE(values+23) = VAL_TYPE(values+24) = VAL_TYPE(values+25) = DB_STR; /* lock the entry */ entry = (d_table->entries)[cell->h_entry]; dlg_lock( d_table, &entry); SET_INT_VALUE(values, cell->h_entry); SET_INT_VALUE(values+1, cell->h_id); SET_STR_VALUE(values+2, cell->callid); SET_STR_VALUE(values+3, cell->from_uri); SET_STR_VALUE(values+4, cell->legs[DLG_CALLER_LEG].tag); SET_STR_VALUE(values+5, cell->to_uri); SET_STR_VALUE(values+6, cell->legs[callee_leg].tag); SET_STR_VALUE(values+7, cell->legs[DLG_CALLER_LEG].bind_addr->sock_str); if (cell->legs[callee_leg].bind_addr) { SET_STR_VALUE(values+8, cell->legs[callee_leg].bind_addr->sock_str); } else { VAL_NULL(values+8) = 1; } SET_INT_VALUE(values+9, cell->start_ts); SET_STR_VALUE(values+10,cell->legs[callee_leg].from_uri); SET_STR_VALUE(values+11,cell->legs[callee_leg].to_uri); SET_INT_VALUE(values+12, cell->state); SET_INT_VALUE(values+13, (unsigned int)( (unsigned int)time(0) + cell->tl.timeout - get_ticks()) ); SET_STR_VALUE(values+14, cell->legs[DLG_CALLER_LEG].r_cseq); SET_STR_VALUE(values+15, cell->legs[callee_leg].r_cseq); SET_INT_VALUE(values+16,cell->legs[DLG_CALLER_LEG].last_gen_cseq); SET_INT_VALUE(values+17,cell->legs[callee_leg].last_gen_cseq); SET_INT_VALUE(values+18, cell->flags & ~(DLG_FLAG_NEW|DLG_FLAG_CHANGED|DLG_FLAG_VP_CHANGED)); set_final_update_cols(values+19, cell, 0); SET_STR_VALUE(values+22, cell->legs[DLG_CALLER_LEG].route_set); SET_STR_VALUE(values+23, cell->legs[callee_leg].route_set); SET_STR_VALUE(values+24, cell->legs[DLG_CALLER_LEG].contact); SET_STR_VALUE(values+25, cell->legs[callee_leg].contact); CON_PS_REFERENCE(dialog_db_handle) = &my_ps_insert; if((dialog_dbf.insert(dialog_db_handle, insert_keys, values, DIALOG_TABLE_TOTAL_COL_NO)) !=0){ LM_ERR("could not add another dialog to db\n"); goto error; } /* dialog saved */ run_dlg_callbacks( DLGCB_SAVED, cell, 0, DLG_DIR_NONE, 0); cell->flags &= ~(DLG_FLAG_NEW|DLG_FLAG_CHANGED|DLG_FLAG_VP_CHANGED); } else if((cell->flags & DLG_FLAG_CHANGED) != 0) { /* save only dialog's state and timeout */ VAL_TYPE(values) = VAL_TYPE(values+1) = VAL_TYPE(values+12) = VAL_TYPE(values+13) = VAL_TYPE(values+16) = VAL_TYPE(values+17) = VAL_TYPE(values+18) = VAL_TYPE(values+21) =DB_INT; VAL_TYPE(values+14) = VAL_TYPE(values+15) = VAL_TYPE(values+19) = VAL_TYPE(values+20) = DB_STR; /* lock the entry */ entry = (d_table->entries)[cell->h_entry]; dlg_lock( d_table, &entry); SET_INT_VALUE(values, cell->h_entry); SET_INT_VALUE(values+1, cell->h_id); SET_INT_VALUE(values+12, cell->state); SET_INT_VALUE(values+13, (unsigned int)( (unsigned int)time(0) + cell->tl.timeout - get_ticks()) ); SET_STR_VALUE(values+14, cell->legs[DLG_CALLER_LEG].r_cseq); SET_STR_VALUE(values+15, cell->legs[callee_leg].r_cseq); SET_INT_VALUE(values+16,cell->legs[DLG_CALLER_LEG].last_gen_cseq); SET_INT_VALUE(values+17,cell->legs[callee_leg].last_gen_cseq); SET_INT_VALUE(values+18, cell->flags); set_final_update_cols(values+19, cell, 1); CON_PS_REFERENCE(dialog_db_handle) = &my_ps_update; if((dialog_dbf.update(dialog_db_handle, (insert_keys), 0, (values), (insert_keys+12), (values+12), 2, 10)) !=0){ LM_ERR("could not update database info\n"); goto error; } /* dialog saved */ run_dlg_callbacks( DLGCB_SAVED, cell, 0, DLG_DIR_NONE, 0); cell->flags &= ~(DLG_FLAG_CHANGED|DLG_FLAG_VP_CHANGED); } else if (cell->flags & DLG_FLAG_VP_CHANGED) { cell->flags |= DLG_FLAG_VP_CHANGED; VAL_TYPE(values) = VAL_TYPE(values+1) = VAL_TYPE(values+21) = DB_INT; VAL_TYPE(values+19) = VAL_TYPE(values+20) = DB_STR; /* lock the entry */ entry = (d_table->entries)[cell->h_entry]; dlg_lock( d_table, &entry); SET_INT_VALUE(values, cell->h_entry); SET_INT_VALUE(values+1, cell->h_id); set_final_update_cols(values+19, cell, 0); CON_PS_REFERENCE(dialog_db_handle) = &my_ps_update_vp; if((dialog_dbf.update(dialog_db_handle, (insert_keys), 0, (values), (insert_keys+19), (values+19), 2, 3)) !=0){ LM_ERR("could not update database info\n"); goto error; } run_dlg_callbacks( DLGCB_SAVED, cell, 0, DLG_DIR_NONE, 0); cell->flags &= ~DLG_FLAG_VP_CHANGED; } else { return 0; } dlg_unlock( d_table, &entry); return 0; error: dlg_unlock( d_table, &entry); return -1; }
/*load rules from DB*/ int dp_load_db(dp_connection_list_p dp_conn) { int i, nr_rows; db_res_t * res = 0; db_val_t * values; db_row_t * rows; db_key_t query_cols[DP_TABLE_COL_NO] = { &dpid_column, &pr_column, &match_op_column, &match_exp_column, &match_flags_column, &subst_exp_column, &repl_exp_column, &attrs_column, &timerec_column }; db_key_t order = &pr_column; /* disabled condition */ db_key_t cond_cols[1] = { &disabled_column }; db_val_t cond_val[1]; dpl_node_t *rule; int no_rows = 10; lock_start_write( dp_conn->ref_lock ); if( dp_conn->crt_index != dp_conn->next_index){ LM_WARN("a load command already generated, aborting reload...\n"); lock_stop_write( dp_conn->ref_lock ); return 0; } dp_conn->next_index = dp_conn->crt_index == 0 ? 1 : 0; lock_stop_write( dp_conn->ref_lock ); if (dp_conn->dp_dbf.use_table(*dp_conn->dp_db_handle, &dp_conn->table_name) < 0){ LM_ERR("error in use_table\n"); goto err1; } VAL_TYPE(cond_val) = DB_INT; VAL_NULL(cond_val) = 0; VAL_INT(cond_val) = 0; if (DB_CAPABILITY(dp_conn->dp_dbf, DB_CAP_FETCH)) { if(dp_conn->dp_dbf.query(*dp_conn->dp_db_handle,cond_cols, 0,cond_val,query_cols,1, DP_TABLE_COL_NO, order, 0) < 0){ LM_ERR("failed to query database!\n"); goto err1; } no_rows = estimate_available_rows( 4+4+4+64+4+64+64+128, DP_TABLE_COL_NO); if (no_rows==0) no_rows = 10; if(dp_conn->dp_dbf.fetch_result(*dp_conn->dp_db_handle, &res, no_rows)<0) { LM_ERR("failed to fetch\n"); if (res) dp_conn->dp_dbf.free_result(*dp_conn->dp_db_handle, res); goto err1; } } else { /*select the whole table and all the columns*/ if(dp_conn->dp_dbf.query(*dp_conn->dp_db_handle, cond_cols,0,cond_val,query_cols,1, DP_TABLE_COL_NO, order, &res) < 0){ LM_ERR("failed to query database\n"); goto err1; } } nr_rows = RES_ROW_N(res); if(nr_rows == 0){ LM_WARN("no data in the db\n"); goto end; } do { for(i=0; i<RES_ROW_N(res); i++){ rows = RES_ROWS(res); values = ROW_VALUES(rows+i); if ((rule = build_rule(values)) == NULL) { LM_WARN(" failed to build rule -> skipping\n"); continue; } rule->table_id = i; if(add_rule2hash(rule , dp_conn, dp_conn->next_index) != 0) { LM_ERR("add_rule2hash failed\n"); goto err2; } } if (DB_CAPABILITY(dp_conn->dp_dbf, DB_CAP_FETCH)) { if(dp_conn->dp_dbf.fetch_result(*dp_conn->dp_db_handle, &res, no_rows)<0) { LM_ERR("failure while fetching!\n"); if (res) dp_conn->dp_dbf.free_result(*dp_conn->dp_db_handle, res); goto err1; } } else { break; } } while(RES_ROW_N(res)>0); end: /*update data*/ lock_start_write( dp_conn->ref_lock ); destroy_hash(&dp_conn->hash[dp_conn->crt_index]); dp_conn->crt_index = dp_conn->next_index; lock_stop_write( dp_conn->ref_lock ); list_hash(dp_conn->hash[dp_conn->crt_index], dp_conn->ref_lock); dp_conn->dp_dbf.free_result(*dp_conn->dp_db_handle, res); return 0; err1: lock_start_write( dp_conn->ref_lock ); dp_conn->next_index = dp_conn->crt_index; lock_stop_write( dp_conn->ref_lock ); return -1; err2: if(rule) destroy_rule(rule); destroy_hash(&dp_conn->hash[dp_conn->next_index]); dp_conn->dp_dbf.free_result(*dp_conn->dp_db_handle, res); lock_start_write( dp_conn->ref_lock ); dp_conn->next_index = dp_conn->crt_index; /* if lock defined - release the exclusive writing access */ lock_stop_write( dp_conn->ref_lock ); return -1; }
/* * Matches from uri against patterns returned from database. Returns number * of matches or -1 if none of the patterns match. */ static int match_res(struct sip_msg* msg, int proto, db1_res_t* _r) { int i, tag_avp_type; str uri; char uri_string[MAX_URI_SIZE+1]; db_row_t* row; db_val_t* val; regex_t preg; int_str tag_avp, avp_val; int count = 0; if (IS_SIP(msg)) { if (parse_from_header(msg) < 0) return -1; uri = get_from(msg)->uri; if (uri.len > MAX_URI_SIZE) { LM_ERR("message has From URI too large\n"); return -1; } memcpy(uri_string, uri.s, uri.len); uri_string[uri.len] = (char)0; } get_tag_avp(&tag_avp, &tag_avp_type); row = RES_ROWS(_r); for(i = 0; i < RES_ROW_N(_r); i++) { val = ROW_VALUES(row + i); if ((ROW_N(row + i) == 3) && (VAL_TYPE(val) == DB1_STRING) && !VAL_NULL(val) && match_proto(VAL_STRING(val), proto) && (VAL_NULL(val + 1) || ((VAL_TYPE(val + 1) == DB1_STRING) && !VAL_NULL(val + 1))) && (VAL_NULL(val + 2) || ((VAL_TYPE(val + 2) == DB1_STRING) && !VAL_NULL(val + 2)))) { if (!VAL_NULL(val + 1) && IS_SIP(msg)) { if (regcomp(&preg, (char *)VAL_STRING(val + 1), REG_NOSUB)) { LM_ERR("invalid regular expression\n"); continue; } if (regexec(&preg, uri_string, 0, (regmatch_t *)0, 0)) { regfree(&preg); continue; } regfree(&preg); } /* Found a match */ if (tag_avp.n && !VAL_NULL(val + 2)) { avp_val.s.s = (char *)VAL_STRING(val + 2); avp_val.s.len = strlen(avp_val.s.s); if (add_avp(tag_avp_type|AVP_VAL_STR, tag_avp, avp_val) != 0) { LM_ERR("failed to set of tag_avp failed\n"); return -1; } } if (!peer_tag_mode) return 1; count++; } } if (!count) return -1; else return count; }
/* * Insert a row into specified table * h: structure representing database connection * k: key names * v: values of the keys * n: number of key=value pairs */ int flat_db_insert(const db_con_t* h, const db_key_t* k, const db_val_t* v, const int n) { FILE* f; int i; int auxl; str aux; char * begin = flat_iov_buf.s; if (local_timestamp < *flat_rotate) { flat_rotate_logs(); local_timestamp = *flat_rotate; } if ( !h || !CON_TAIL(h) || (f=CON_FILE(h))==NULL ) { LM_ERR("uninitialized connection\n"); return -1; } if (flat_prepare_iovec(n) < 0) { LM_ERR("cannot insert row\n"); return -1; } FLAT_LOCK(f); for(i = 0; i < n; i++) { if (VAL_NULL(v + i)) { FLAT_SET_STR(i, ""); FLAT_SET_LEN(i, 0); continue; } FLAT_SET_STR(i, FLAT_BUF); switch(VAL_TYPE(v + i)) { case DB_INT: /* guess this is 20 */ FLAT_ALLOC(20); FLAT_PRINTF("%d", VAL_INT(v+i), i); break; case DB_DOUBLE: /* guess there are max 20 digits */ FLAT_ALLOC(40); FLAT_PRINTF("%f", VAL_DOUBLE(v+i), i); break; case DB_BIGINT: /* guess there are max 20 digits */ FLAT_ALLOC(40); FLAT_PRINTF("%llu", VAL_BIGINT(v+i), i); break; case DB_STRING: auxl = strlen(VAL_STRING(v + i)); FLAT_ALLOC(auxl * 4); FLAT_COPY(i, VAL_STRING(v + i), auxl); break; case DB_STR: FLAT_ALLOC(VAL_STR(v + i).len * 4); FLAT_COPY(i, VAL_STR(v + i).s, VAL_STR(v + i).len); break; case DB_DATETIME: /* guess this is 20 */ FLAT_ALLOC(20); FLAT_PRINTF("%lu", VAL_TIME(v+i), i); break; case DB_BLOB: auxl = VAL_BLOB(v+i).len; /* the maximum size is 4l - if all chars were not printable */ FLAT_ALLOC(4 * auxl); FLAT_COPY(i, VAL_BLOB(v+i).s, auxl); break; case DB_BITMAP: /* guess this is 20 */ FLAT_ALLOC(20); FLAT_PRINTF("%u", VAL_BITMAP(v+i), i); break; } } /* reorder pointers in case they were altered by (re)allocation */ if (flat_iov_buf.s != begin && flat_iov_buf.len) { FLAT_RESET(); for (i = 0; i < n; i++) { if (!VAL_NULL(v + i)) { FLAT_SET_STR(i, FLAT_BUF); FLAT_INC(FLAT_GET_LEN(i)); } } } do { auxl = writev(fileno(f), flat_iov, 2 * n); } while (auxl < 0 && errno == EINTR); if (auxl < 0) { LM_ERR("unable to write to file: %s - %d\n", strerror(errno), errno); return -1; } /* XXX does this make sense any more? */ if (flat_flush && fflush(f) < 0) { LM_ERR("cannot flush buffer: %s - %d\n", strerror(errno), errno); } FLAT_UNLOCK(f); return 0; }
/* * Reload trusted table to new hash table and when done, make new hash table * current one. */ int reload_trusted_table(void) { db_key_t cols[4]; db1_res_t* res = NULL; db_row_t* row; db_val_t* val; struct trusted_list **new_hash_table; int i; char *pattern, *tag; cols[0] = &source_col; cols[1] = &proto_col; cols[2] = &from_col; cols[3] = &tag_col; if (db_handle == 0) { LM_ERR("no connection to database\n"); return -1; } if (perm_dbf.use_table(db_handle, &trusted_table) < 0) { LM_ERR("failed to use trusted table\n"); return -1; } if (perm_dbf.query(db_handle, NULL, 0, NULL, cols, 0, 4, 0, &res) < 0) { LM_ERR("failed to query database\n"); return -1; } /* Choose new hash table and free its old contents */ if (*hash_table == hash_table_1) { empty_hash_table(hash_table_2); new_hash_table = hash_table_2; } else { empty_hash_table(hash_table_1); new_hash_table = hash_table_1; } row = RES_ROWS(res); LM_DBG("number of rows in trusted table: %d\n", RES_ROW_N(res)); for (i = 0; i < RES_ROW_N(res); i++) { val = ROW_VALUES(row + i); if ((ROW_N(row + i) == 4) && (VAL_TYPE(val) == DB1_STRING) && !VAL_NULL(val) && (VAL_TYPE(val + 1) == DB1_STRING) && !VAL_NULL(val + 1) && (VAL_NULL(val + 2) || ((VAL_TYPE(val + 2) == DB1_STRING) && !VAL_NULL(val + 2))) && (VAL_NULL(val + 3) || ((VAL_TYPE(val + 3) == DB1_STRING) && !VAL_NULL(val + 3)))) { if (VAL_NULL(val + 2)) { pattern = 0; } else { pattern = (char *)VAL_STRING(val + 2); } if (VAL_NULL(val + 3)) { tag = 0; } else { tag = (char *)VAL_STRING(val + 3); } if (hash_table_insert(new_hash_table, (char *)VAL_STRING(val), (char *)VAL_STRING(val + 1), pattern, tag) == -1) { LM_ERR("hash table problem\n"); perm_dbf.free_result(db_handle, res); return -1; } LM_DBG("tuple <%s, %s, %s, %s> inserted into trusted hash " "table\n", VAL_STRING(val), VAL_STRING(val + 1), pattern, tag); } else { LM_ERR("database problem\n"); perm_dbf.free_result(db_handle, res); return -1; } } perm_dbf.free_result(db_handle, res); *hash_table = new_hash_table; LM_DBG("trusted table reloaded successfully.\n"); return 1; }
int load_data(db_func_t * dbf, db1_con_t * dbh, ul_db_handle_t * handle, int id){ db1_res_t *res; db_row_t *row; db_key_t cols[7]; db_key_t keys[2]; db_val_t key_vals[2]; db_op_t op[2]; db_key_t order; int i, ret = 0; if(!dbf || !dbh || !handle){ LM_ERR("NULL-Pointer in Parameter\n"); return -1; } memset(handle, 0, sizeof(ul_db_handle_t)); cols[0] = &num_col; cols[1] = &url_col; cols[2] = &status_col; cols[3] = &failover_time_col; cols[4] = &spare_col; cols[5] = &error_col; cols[6] = &risk_group_col; order = &num_col; keys[0] = &id_col; op[0] = OP_EQ; key_vals[0].type = DB1_INT; key_vals[0].nul = 0; key_vals[0].val.int_val = id; if(dbf->use_table(dbh, ®_table) < 0){ LM_ERR("could't use table.\n"); return -1; } if(dbf->query(dbh, keys, op, key_vals, cols, 1, 7, order, &res) < 0){ LM_ERR("error while doing db query.\n"); return -1; } if(RES_ROW_N(res) < DB_NUM) { LM_ERR("keys have too few location databases\n"); ret = -1; goto ret; } handle->id = id; for(i=0; i<DB_NUM; i++) { row = RES_ROWS(res) + i; handle->db[i].no = (int)VAL_INT(ROW_VALUES(row)); if(VAL_NULL(ROW_VALUES(row) + 1)){ LM_ERR("Weird: Empty database URL\n"); ret = -1; goto ret; } if(strlen((char *)VAL_STRING(ROW_VALUES(row) + 1)) >= (UL_DB_URL_LEN - 1)){ LM_ERR("weird: very large URL (%d Bytes)\n", (int)(strlen((char *)VAL_STRING(ROW_VALUES(row) + 1)) + 1)); ret = -1; goto ret; } strcpy(handle->db[i].url.s, (char *)VAL_STRING(ROW_VALUES(row) + 1)); handle->db[i].url.len = strlen(handle->db[i].url.s); handle->db[i].status = (int)VAL_INT(ROW_VALUES(row) + 2); handle->db[i].failover_time = VAL_TIME (ROW_VALUES(row) + 3); handle->db[i].spare = VAL_INT (ROW_VALUES(row) + 4); handle->db[i].errors = VAL_INT (ROW_VALUES(row) + 5); handle->db[i].rg = VAL_INT (ROW_VALUES(row) + 6); } ret: dbf->free_result(dbh, res); return ret; }
/* select data from emergency_routing and put in memory * coluns keys: srid(selectiveRoutingID), resn(routingESN) and npa. * coluns translate: esgwri */ int get_db_routing(str table_name, rw_lock_t *ref_lock ){ db_key_t query_cols[] = {&id_col, &srid_col, &resn_col, &npa_col, &esgwri_col}; db_res_t * res; db_val_t * values; db_row_t * rows; str esgwri; str SRID; int RESN; int NPA; int nr_rows, i, size, id; struct esrn_routing *esrn_cell, *old_list, *it, *aux, *new_list; struct esrn_routing *init_esrn = NULL; db_funcs.use_table(db_con, &table_name); /* select value from routing table * the keys of routing table: selectiveRoutingID, routingESN, npa * the result of routing lookup: esgwri */ if (db_funcs.query(db_con, 0, 0, 0, query_cols, 0, 5, 0, &res) != 0) { LM_ERR("Failure to issue query\n"); return -1; } nr_rows = RES_ROW_N(res); rows = RES_ROWS(res); new_list = NULL; LM_DBG("NUMBER OF LINES ROUTING %d \n", nr_rows); for (i = 0; i < nr_rows; i++) { values = ROW_VALUES(rows + i); if (VAL_NULL(values) || (VAL_TYPE(values) != DB_INT)) { LM_ERR("Invalid value returned 1\n"); goto end; } id = VAL_INT(values); if (VAL_NULL(values + 1) || (VAL_TYPE(values + 1) != DB_STR && VAL_TYPE(values + 1) != DB_STRING)) { LM_ERR("Invalid translated returned 2\n"); goto end; } if (VAL_TYPE(values + 1) == DB_STR) { SRID = VAL_STR(values + 1); } else { SRID.s = (char*) VAL_STRING(values + 1); SRID.len = strlen(SRID.s); } if (VAL_NULL(values + 2) || (VAL_TYPE(values + 2) != DB_INT)) { LM_ERR("Invalid translated returned 3\n"); goto end; } RESN = VAL_INT(values + 2); if (VAL_NULL(values + 3) || (VAL_TYPE(values + 3) != DB_INT)) { LM_ERR("Invalid translated returned 4\n"); goto end; } NPA = VAL_INT(values + 3); if (VAL_NULL(values + 4) || (VAL_TYPE(values + 4) != DB_STR && VAL_TYPE(values + 4) != DB_STRING)) { LM_ERR("Invalid translated returned 5\n"); goto end; } if (VAL_TYPE(values + 4) == DB_STR) { esgwri = VAL_STR(values + 4); } else { esgwri.s = (char*) VAL_STRING(values + 4); esgwri.len = strlen(esgwri.s); } size = sizeof (struct esrn_routing)+SRID.len + esgwri.len; esrn_cell = shm_malloc(size); if (!esrn_cell) { LM_ERR("no more shm\n"); goto end; } memset(esrn_cell, 0, size); esrn_cell->srid.len = SRID.len; esrn_cell->srid.s = (char *) (esrn_cell + 1); memcpy(esrn_cell->srid.s, SRID.s, SRID.len); esrn_cell->resn = RESN; esrn_cell->npa = NPA; esrn_cell->esgwri.len = esgwri.len; esrn_cell->esgwri.s = (char *) (esrn_cell + 1) + SRID.len; memcpy(esrn_cell->esgwri.s, esgwri.s, esgwri.len); LM_DBG("-SRID %.*s \n", SRID.len, SRID.s); LM_DBG("-RESN %d \n", RESN); LM_DBG("-NPA %d \n", NPA); LM_DBG("-esgwri %.*s \n", esgwri.len, esgwri.s); if (new_list != NULL) { new_list->next = esrn_cell; new_list = esrn_cell; } else { new_list = esrn_cell; init_esrn = new_list; } } new_list = init_esrn; lock_start_write(ref_lock); old_list = *db_esrn_esgwri; *db_esrn_esgwri = init_esrn; lock_stop_write(ref_lock); it = old_list; while (it) { aux = it; it = it->next; shm_free(aux); } end: db_funcs.free_result(db_con, res); return 1; }
/* * Add key-value to a bson document */ int db_mongodb_bson_add(bson_t *doc, const db_key_t _k, const db_val_t *_v, int idx) { int vtype; vtype = VAL_TYPE(_v); if(VAL_NULL(_v)) { if(!bson_append_null(doc, _k->s, _k->len)) { LM_ERR("failed to append int to bson doc %.*s = %d [%d]\n", _k->len, _k->s, VAL_INT(_v), idx); goto error; } goto done; } switch(vtype) { case DB1_INT: if(!bson_append_int32(doc, _k->s, _k->len, VAL_INT(_v))) { LM_ERR("failed to append int to bson doc %.*s = %d [%d]\n", _k->len, _k->s, VAL_INT(_v), idx); goto error; } break; case DB1_BIGINT: if(!bson_append_int64(doc, _k->s, _k->len, VAL_BIGINT(_v ))) { LM_ERR("failed to append bigint to bson doc %.*s = %lld [%d]\n", _k->len, _k->s, VAL_BIGINT(_v), idx); goto error; } return -1; case DB1_DOUBLE: if(!bson_append_double(doc, _k->s, _k->len, VAL_DOUBLE(_v))) { LM_ERR("failed to append double to bson doc %.*s = %f [%d]\n", _k->len, _k->s, VAL_DOUBLE(_v), idx); goto error; } break; case DB1_STRING: if(!bson_append_utf8(doc, _k->s, _k->len, VAL_STRING(_v), strlen(VAL_STRING(_v))) ) { LM_ERR("failed to append string to bson doc %.*s = %s [%d]\n", _k->len, _k->s, VAL_STRING(_v), idx); goto error; } break; case DB1_STR: if(!bson_append_utf8(doc, _k->s, _k->len, VAL_STR(_v).s, VAL_STR(_v).len) ) { LM_ERR("failed to append str to bson doc %.*s = %.*s [%d]\n", _k->len, _k->s, VAL_STR(_v).len, VAL_STR(_v).s, idx); goto error; } break; case DB1_DATETIME: if(!bson_append_time_t(doc, _k->s, _k->len, VAL_TIME(_v))) { LM_ERR("failed to append time to bson doc %.*s = %ld [%d]\n", _k->len, _k->s, VAL_TIME(_v), idx); goto error; } break; case DB1_BLOB: if(!bson_append_binary(doc, _k->s, _k->len, BSON_SUBTYPE_BINARY, (const uint8_t *)VAL_BLOB(_v).s, VAL_BLOB(_v).len) ) { LM_ERR("failed to append blob to bson doc %.*s = [bin] [%d]\n", _k->len, _k->s, idx); goto error; } break; case DB1_BITMAP: if(!bson_append_int32(doc, _k->s, _k->len, VAL_INT(_v))) { LM_ERR("failed to append bitmap to bson doc %.*s = %d [%d]\n", _k->len, _k->s, VAL_INT(_v), idx); goto error; } break; default: LM_ERR("val type [%d] not supported\n", vtype); return -1; } done: return 0; error: return -1; }
/* select data from emergency_service_prvider for put in xml to VPC * coluns key: attribution and nodeIP. * coluns attributs: OrganizationName, hostId, nenaId, contact, certUri. */ int get_db_provider(str table_name, rw_lock_t *ref_lock ){ db_key_t query_cols[] = {&id_col, &organizationName_col, &hostId_col, &nenaId_col, &contact_col, &certUri_col, &nodeIP_col, &attribution_col}; db_res_t * res; db_val_t * values; db_row_t * rows; str OrganizationName; str hostId; str nenaId; str contact; str certUri; str nodeIP; int attribution; int nr_rows, i, size, id; struct service_provider *provider_cell, *old_list, *it, *aux, *new_list; struct service_provider *init_provider = NULL; db_funcs.use_table(db_con, &table_name); if (db_funcs.query(db_con, 0, 0, 0, query_cols, 0, 8, 0, &res) != 0) { LM_ERR("Failure to issue query\n"); return -1; } nr_rows = RES_ROW_N(res); rows = RES_ROWS(res); new_list = NULL; LM_DBG("NUMBER OF LINES %d \n", nr_rows); for (i = 0; i < nr_rows; i++) { values = ROW_VALUES(rows + i); if (VAL_NULL(values) || (VAL_TYPE(values) != DB_INT)) { LM_ERR("Invalid value returned 1\n"); goto end; } id = VAL_INT(values); if (VAL_NULL(values + 1) || (VAL_TYPE(values + 1) != DB_STR && VAL_TYPE(values + 1) != DB_STRING)) { LM_ERR("Invalid translated returned 2\n"); goto end; } if (VAL_TYPE(values + 1) == DB_STR) { OrganizationName = VAL_STR(values + 1); } else { OrganizationName.s = (char*) VAL_STRING(values + 1); OrganizationName.len = strlen(OrganizationName.s); } if (VAL_NULL(values + 2) || (VAL_TYPE(values + 2) != DB_STR && VAL_TYPE(values + 2) != DB_STRING)) { LM_ERR("Invalid translated returned 2\n"); goto end; } if (VAL_TYPE(values + 2) == DB_STR) { hostId = VAL_STR(values + 2); } else { hostId.s = (char*) VAL_STRING(values + 2); hostId.len = strlen(hostId.s); } if (VAL_NULL(values + 3) || (VAL_TYPE(values + 3) != DB_STR && VAL_TYPE(values + 3) != DB_STRING)) { LM_ERR("Invalid translated returned 3\n"); goto end; } if (VAL_TYPE(values + 3) == DB_STR) { nenaId = VAL_STR(values + 3); } else { nenaId.s = (char*) VAL_STRING(values + 3); nenaId.len = strlen(nenaId.s); } if (VAL_NULL(values + 4) || (VAL_TYPE(values + 4) != DB_STR && VAL_TYPE(values + 4) != DB_STRING)) { LM_ERR("Invalid translated returned 4\n"); goto end; } if (VAL_TYPE(values + 4) == DB_STR) { contact = VAL_STR(values + 4); } else { contact.s = (char*) VAL_STRING(values + 4); contact.len = strlen(contact.s); } if (VAL_NULL(values + 5) || (VAL_TYPE(values + 5) != DB_STR && VAL_TYPE(values + 5) != DB_STRING)) { LM_ERR("Invalid translated returned 3\n"); goto end; } if (VAL_TYPE(values + 5) == DB_STR) { certUri = VAL_STR(values + 5); } else { certUri.s = (char*) VAL_STRING(values + 5); certUri.len = strlen(certUri.s); } if (VAL_NULL(values + 6) || (VAL_TYPE(values + 6) != DB_STR && VAL_TYPE(values + 6) != DB_STRING)) { LM_ERR("Invalid translated returned 6\n"); goto end; } if (VAL_TYPE(values + 6) == DB_STR) { nodeIP = VAL_STR(values + 6); } else { nodeIP.s = (char*) VAL_STRING(values + 6); nodeIP.len = strlen(nodeIP.s); } if (VAL_NULL(values + 7) || (VAL_TYPE(values + 7) != DB_INT)) { LM_ERR("Invalid translated returned 7\n"); goto end; } attribution = VAL_INT(values + 7); if (attribution == 0){ if (hostId.len == 0 || contact.len == 0) { LM_ERR("source_hostname and source_contact are mandatory \n"); mandatory_parm[0] = '1'; mandatory_parm[1] = 0; } else{ mandatory_parm[0] = '0'; mandatory_parm[1] = 0; } } size = sizeof (struct service_provider)+ nodeIP.len + OrganizationName.len + hostId.len + nenaId.len + contact.len + certUri.len; provider_cell = shm_malloc(size); if (!provider_cell) { LM_ERR("no more shm\n"); goto end; } memset(provider_cell, 0, size); provider_cell->nodeIP.len = nodeIP.len; provider_cell->nodeIP.s = (char *) (provider_cell + 1); memcpy(provider_cell->nodeIP.s, nodeIP.s, nodeIP.len); provider_cell->OrganizationName.len = OrganizationName.len; provider_cell->OrganizationName.s = (char *) (provider_cell + 1) + nodeIP.len; memcpy(provider_cell->OrganizationName.s, OrganizationName.s, OrganizationName.len); provider_cell->hostId.len = hostId.len; provider_cell->hostId.s = (char *) (provider_cell + 1) + nodeIP.len + OrganizationName.len; memcpy(provider_cell->hostId.s, hostId.s, hostId.len); provider_cell->nenaId.len = nenaId.len; provider_cell->nenaId.s = (char *) (provider_cell + 1) + nodeIP.len + OrganizationName.len + hostId.len; memcpy(provider_cell->nenaId.s, nenaId.s, nenaId.len); provider_cell->contact.len = contact.len; provider_cell->contact.s = (char *) (provider_cell + 1) + nodeIP.len + OrganizationName.len + hostId.len + nenaId.len; memcpy(provider_cell->contact.s, contact.s, contact.len); provider_cell->certUri.len = certUri.len; provider_cell->certUri.s = (char *) (provider_cell + 1) + nodeIP.len + OrganizationName.len + hostId.len + nenaId.len + contact.len; memcpy(provider_cell->certUri.s, certUri.s, certUri.len); provider_cell->attribution = attribution; if (new_list != NULL) { new_list->next = provider_cell; new_list = provider_cell; } else { new_list = provider_cell; init_provider = new_list; } } new_list = init_provider; lock_start_write(ref_lock); old_list = *db_service_provider; *db_service_provider = init_provider; lock_stop_write(ref_lock); it = old_list; while (it) { aux = it; it = it->next; shm_free(aux); } end: db_funcs.free_result(db_con, res); return 1; }
/* * Add key-op-value to a bson filter document */ int db_mongodb_bson_filter_add(bson_t *doc, const db_key_t* _k, const db_op_t* _op, const db_val_t* _v, int idx) { bson_t mdoc; db_key_t tkey; const db_val_t *tval; int vtype; str ocmp; tkey = _k[idx]; tval = _v + idx; vtype = VAL_TYPE(tval); /* OP_EQ is handled separately */ if(!strcmp(_op[idx], OP_LT)) { ocmp.s = "$lt"; ocmp.len = 3; } else if(!strcmp(_op[idx], OP_LEQ)) { ocmp.s = "$lte"; ocmp.len = 4; } else if(!strcmp(_op[idx], OP_GT)) { ocmp.s = "$gt"; ocmp.len = 3; } else if(!strcmp(_op[idx], OP_GEQ)) { ocmp.s = "$gte"; ocmp.len = 4; } else if(!strcmp(_op[idx], OP_NEQ) || !strcmp(_op[idx], "!=")) { ocmp.s = "$ne"; ocmp.len = 3; } else { LM_ERR("unsuported match operator: %s\n", _op[idx]); goto error; } if(!bson_append_document_begin(doc, tkey->s, tkey->len, &mdoc)) { LM_ERR("failed to append start to bson doc %.*s %s ... [%d]\n", tkey->len, tkey->s, ocmp.s, idx); goto error; } if(VAL_NULL(tval)) { if(!bson_append_null(&mdoc, ocmp.s, ocmp.len)) { LM_ERR("failed to append null to bson doc %.*s %s null [%d]\n", tkey->len, tkey->s, ocmp.s, idx); goto error; } goto done; } switch(vtype) { case DB1_INT: if(!bson_append_int32(&mdoc, ocmp.s, ocmp.len, VAL_INT(tval))) { LM_ERR("failed to append int to bson doc %.*s %s %d [%d]\n", tkey->len, tkey->s, ocmp.s, VAL_INT(tval), idx); goto error; } break; case DB1_BIGINT: if(!bson_append_int64(&mdoc, ocmp.s, ocmp.len, VAL_BIGINT(tval ))) { LM_ERR("failed to append bigint to bson doc %.*s %s %lld [%d]\n", tkey->len, tkey->s, ocmp.s, VAL_BIGINT(tval), idx); goto error; } return -1; case DB1_DOUBLE: if(!bson_append_double(&mdoc, ocmp.s, ocmp.len, VAL_DOUBLE(tval))) { LM_ERR("failed to append double to bson doc %.*s %s %f [%d]\n", tkey->len, tkey->s, ocmp.s, VAL_DOUBLE(tval), idx); goto error; } break; case DB1_STRING: if(!bson_append_utf8(&mdoc, ocmp.s, ocmp.len, VAL_STRING(tval), strlen(VAL_STRING(tval))) ) { LM_ERR("failed to append string to bson doc %.*s %s %s [%d]\n", tkey->len, tkey->s, ocmp.s, VAL_STRING(tval), idx); goto error; } break; case DB1_STR: if(!bson_append_utf8(&mdoc, ocmp.s, ocmp.len, VAL_STR(tval).s, VAL_STR(tval).len) ) { LM_ERR("failed to append str to bson doc %.*s %s %.*s [%d]\n", tkey->len, tkey->s, ocmp.s, VAL_STR(tval).len, VAL_STR(tval).s, idx); goto error; } break; case DB1_DATETIME: if(!bson_append_time_t(&mdoc, ocmp.s, ocmp.len, VAL_TIME(tval))) { LM_ERR("failed to append time to bson doc %.*s %s %ld [%d]\n", tkey->len, tkey->s, ocmp.s, VAL_TIME(tval), idx); goto error; } break; case DB1_BLOB: if(!bson_append_binary(&mdoc, ocmp.s, ocmp.len, BSON_SUBTYPE_BINARY, (const uint8_t *)VAL_BLOB(tval).s, VAL_BLOB(tval).len) ) { LM_ERR("failed to append blob to bson doc %.*s %s [bin] [%d]\n", tkey->len, tkey->s, ocmp.s, idx); goto error; } break; case DB1_BITMAP: if(!bson_append_int32(&mdoc, ocmp.s, ocmp.len, VAL_INT(tval))) { LM_ERR("failed to append bitmap to bson doc %.*s %s %d [%d]\n", tkey->len, tkey->s, ocmp.s, VAL_INT(tval), idx); goto error; } break; default: LM_ERR("val type [%d] not supported\n", vtype); goto error; } done: if(!bson_append_document_end(doc, &mdoc)) { LM_ERR("failed to append end to bson doc %.*s %s ... [%d]\n", tkey->len, tkey->s, ocmp.s, idx); goto error; } return 0; error: return -1; }
int fetch_credentials(sip_msg_t *msg, str *user, str* domain, str *table, int flags) { pv_elem_t *cred; db_key_t keys[2]; db_val_t vals[2]; db_key_t *col; db1_res_t *res = NULL; int n, nc; if(flags&AUTH_DB_SUBS_SKIP_CREDENTIALS) { nc = 1; } else { nc = credentials_n; } col = pkg_malloc(sizeof(*col) * (nc+1)); if (col == NULL) { LM_ERR("no more pkg memory\n"); return -1; } keys[0] = &user_column; keys[1] = &domain_column; if(flags&AUTH_DB_SUBS_SKIP_CREDENTIALS) { col[0] = &user_column; } else { for (n = 0, cred=credentials; cred ; n++, cred=cred->next) { col[n] = &cred->text; } } VAL_TYPE(vals) = VAL_TYPE(vals + 1) = DB1_STR; VAL_NULL(vals) = VAL_NULL(vals + 1) = 0; n = 1; VAL_STR(vals) = *user; if (domain && domain->len) { VAL_STR(vals + 1) = *domain; n = 2; } if (auth_dbf.use_table(auth_db_handle, table) < 0) { LM_ERR("failed to use_table\n"); pkg_free(col); return -1; } if (auth_dbf.query(auth_db_handle, keys, 0, vals, col, n, nc, 0, &res) < 0) { LM_ERR("failed to query database\n"); pkg_free(col); if(res) auth_dbf.free_result(auth_db_handle, res); return -1; } pkg_free(col); if (RES_ROW_N(res) == 0) { if(res) auth_dbf.free_result(auth_db_handle, res); LM_DBG("no result for user \'%.*s%s%.*s\' in [%.*s]\n", user->len, user->s, (n==2)?"@":"", (n==2)?domain->len:0, (n==2)?domain->s:"", table->len, table->s); return -2; } if(flags&AUTH_DB_SUBS_SKIP_CREDENTIALS) { /* there is a result and flag to skip loading credentials is set */ goto done; } for (cred=credentials, n=0; cred; cred=cred->next, n++) { if (db_val2pv_spec(msg, &RES_ROWS(res)[0].values[n], cred->spec) != 0) { if(res) auth_dbf.free_result(auth_db_handle, res); LM_ERR("Failed to convert value for column %.*s\n", RES_NAMES(res)[n]->len, RES_NAMES(res)[n]->s); return -3; } } done: if(res) auth_dbf.free_result(auth_db_handle, res); return 0; }