void destroy_cachedb(void) { if (cdbc) cdbf.destroy(cdbc); if (rl_name_buffer.s) pkg_free(rl_name_buffer.s); }
int init_cachedb(str * db_url) { if (cachedb_bind_mod(db_url, &cdbf) < 0) { LM_ERR("cannot bind functions for db_url %.*s\n", db_url->len, db_url->s); return -1; } if (!CACHEDB_CAPABILITY(&cdbf, CACHEDB_CAP_GET|CACHEDB_CAP_ADD|CACHEDB_CAP_SUB)) { LM_ERR("not enough capabilities\n"); return -1; } cdbc = cdbf.init(db_url); if (!cdbc) { LM_ERR("cannot connect to db_url %.*s\n", db_url->len, db_url->s); return -1; } /* guessing that the name is not larger than 32 */ rl_name_buffer.len = db_prefix.len + 32; rl_name_buffer.s = pkg_malloc(rl_name_buffer.len); if (!rl_name_buffer.s) { LM_ERR("no more pkg memory\n"); rl_name_buffer.len = 0; return -1; } /* copy prefix - this is constant*/ memcpy(rl_name_buffer.s, db_prefix.s, db_prefix.len); return 0; }
/* NOTE: assumes that the pipe has been locked. If fails, releases the lock */ static int rl_get_counter(str *name, rl_pipe_t * pipe) { str res; unsigned int hid = RL_GET_INDEX(*name); int new_counter; RL_SET_PENDING(pipe); RL_RELEASE_LOCK(hid); if (rl_set_name(name) < 0) return -1; if (cdbf.get(cdbc, &rl_name_buffer, &res) < 0) { LM_ERR("cannot retrieve key\n"); return -1; } if (str2sint(&res, &new_counter) < 0) { LM_ERR("invalid value %.*s - should be integer\n", res.len, res.s); return -1; } if (res.s) pkg_free(res.s); RL_GET_LOCK(hid); RL_RESET_PENDING(pipe); pipe->counter = new_counter; return 0; }
/* NOTE: assumes that the pipe has been locked. If fails, releases the lock */ static int rl_change_counter(str *name, rl_pipe_t *pipe, int c) { int new_counter; if (rl_set_name(name) < 0) return -1; if (pipe->my_counter + c <= 0) { LM_DBG("Counter going negative\n"); return 1; } if (cdbf.add(cdbc, &rl_name_buffer, c ? c : -(pipe->my_counter), rl_expire_time, &new_counter) < 0){ LM_ERR("cannot change counter for pipe %.*s with %d\n", name->len, name->s, c); return -1; } pipe->my_counter = c ? pipe->my_counter + c : 0; pipe->counter = new_counter; LM_DBG("changed with %d; my_counter: %d; counter: %d\n", c, pipe->my_counter, new_counter); return 0; }
/* Pushes internal structure ( hostent or rdata ) to a cache backend * Params : * name - what query to be saved - binary IP for PTR and strings for other queries * r_type - type of DNS query * record - pointer to hostent or rdata * rdata_len - If rdata record, rdata_len holds the actual length of rdata buf, in order to avoid double iterations on the rdata struct. If it's a PTR record, rdata_len is used to differentiate between IP and IPv6 * failure - should we blacklist or not * ttl - seconds the key should be kept in cache */ int put_dnscache_value(char *name,int r_type,void *record,int rdata_len, int failure,int ttl) { str key,value; int key_ttl; if (cdbc == NULL) { /* assume dns request before forking - cache is not ready yet */ return -1; } /* generate key */ key.s=create_keyname_for_record(name,r_type,rdata_len,&key.len); if (key.s == NULL) { LM_ERR("failed to create key\n"); return -1; } if (failure) { /* just set value as failure marker, and push to back-end * with the default timeout */ value.s = FAILURE_MARKER; value.len= FAILURE_MARKER_LEN; key_ttl = blacklist_timeout; } else { if (r_type == T_A || r_type == T_AAAA || r_type == T_PTR) { value.s = serialize_he_rdata((struct hostent *)record, &value.len,CACHEDB_CAPABILITY(&cdbf,CACHEDB_CAP_BINARY_VALUE)?0:1); if (value.s == NULL) { LM_ERR("failed to serialize he rdata\n"); return -1; } } else { value.s = serialize_dns_rdata((struct rdata *)record, rdata_len,&value.len,CACHEDB_CAPABILITY(&cdbf,CACHEDB_CAP_BINARY_VALUE)?0:1); if (value.s == NULL) { LM_ERR("failed to serialize rdata record\n"); return -1; } } key_ttl = ttl; } LM_DBG("putting value [%.*s] with ttl = %d\n",key.len,key.s,key_ttl); if (cdbf.set(cdbc,&key,&value,key_ttl) < 0) { LM_ERR("failed to set dns key\n"); return -1; } return 0; }
/* NOTE: assumes that the pipe has been locked */ static int rl_get_counter(str *name, rl_pipe_t * pipe) { int new_counter; if (rl_set_name(name) < 0) return -1; if (cdbf.get_counter(cdbc, &rl_name_buffer, &new_counter) < 0) { LM_ERR("cannot retrieve key\n"); return -1; } pipe->counter = new_counter; return 0; }
/* NOTE: assumes that the pipe has been locked. If fails, releases the lock */ static int rl_change_counter(str *name, rl_pipe_t *pipe, int c) { unsigned int hid = RL_GET_INDEX(*name); int new_counter; RL_SET_PENDING(pipe); RL_RELEASE_LOCK(hid); if (rl_set_name(name) < 0) return -1; /* if the command should be reset */ /* XXX: This is not needed since add takes also negative numbers if (c > 0) { if (cdbf.add(cdbc, &rl_name_buffer, c, rl_expire_time, &new_counter)<0){ LM_ERR("cannot increase buffer for pipe %.*s\n", name->len, name->s); return -1; } } else { if (cdbf.sub(cdbc, &rl_name_buffer, c ? c : pipe->my_counter, rl_expire_time, &new_counter) < 0){ LM_ERR("cannot change counter for pipe %.*s with %d\n", name->len, name->s, c); return -1; } } */ if (cdbf.add(cdbc, &rl_name_buffer, c ? c : -(pipe->my_counter), rl_expire_time, &new_counter) < 0){ LM_ERR("cannot change counter for pipe %.*s with %d\n", name->len, name->s, c); return -1; } RL_GET_LOCK(hid); RL_RESET_PENDING(pipe); pipe->my_counter = c ? pipe->my_counter + c : 0; pipe->counter = new_counter; LM_DBG("changed with %d; my_counter: %d; counter: %d\n", c, pipe->my_counter, new_counter); return 0; }
/* gets value from cache for the corresponding entry * Params : * name - what is wished to be resolved - binary IP for PTR and strings for other queries * r_type - type of DNS query * name_len - only used in case of PTR */ int get_dnscache_strvalue(char *name,int r_type,int name_len,str *res) { str key; /* generate key */ key.s=create_keyname_for_record(name,r_type,name_len,&key.len); if (key.s == NULL) { LM_ERR("failed to create key\n"); return -1; } LM_DBG("gen key [%.*s]\n",key.len,key.s); /* fetch from backend */ if (cdbf.get(cdbc, &key, res) < 0) { LM_DBG("cannot retrieve key\n"); return -1; } return 0; }
static int child_init(int rank) { if (cachedb_bind_mod(&cachedb_url, &cdbf) < 0) { LM_ERR("cannot bind functions for db_url %.*s\n", cachedb_url.len, cachedb_url.s); return -1; } if (!CACHEDB_CAPABILITY(&cdbf, CACHEDB_CAP_GET|CACHEDB_CAP_SET)) { LM_ERR("not enough capabilities\n"); return -1; } cdbc = cdbf.init(&cachedb_url); if (!cdbc) { LM_ERR("cannot connect to db_url %.*s\n", cachedb_url.len, cachedb_url.s); return -1; } return 0; }
/* * destroy function */ static void destroy(void) { LM_NOTICE("destroy module dns_cache ...\n"); if (cdbc) cdbf.destroy(cdbc); }