/* 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; }
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; }
/* Returns hostent or rdata struct, based on what callers needs */ void* get_dnscache_value(char *name,int r_type,int name_len) { str value; struct hostent *he; struct rdata *head; if (cdbc == NULL) { /* assume dns request before forking - cache is not ready yet */ return NULL; } if (get_dnscache_strvalue(name,r_type,name_len,&value) < 0) { LM_DBG("failed to fetch from cache\n"); return NULL; } if (value.len == FAILURE_MARKER_LEN && value.s[0] == FAILURE_MARKER_CHAR) { LM_DBG("blacklisted value %s for type %d\n",name,r_type); pkg_free(value.s); return (void *)-1; } if (r_type == T_A || r_type == T_AAAA || r_type == T_PTR) { he = deserialize_he_rdata(value.s,value.len, CACHEDB_CAPABILITY(&cdbf,CACHEDB_CAP_BINARY_VALUE)?0:1); if (he == NULL) { LM_ERR("failed to deserialize he struct\n"); pkg_free(value.s); return NULL; } pkg_free(value.s); return he; } else { head = deserialize_dns_rdata(value.s,value.len, CACHEDB_CAPABILITY(&cdbf,CACHEDB_CAP_BINARY_VALUE)?0:1); if (head == NULL) { LM_ERR("failed to deserialize rdata struct\n"); pkg_free(value.s); return NULL; } pkg_free(value.s); return head; } }
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; }