Commit 4080d6d5 authored by Vladimír Čunát's avatar Vladimír Čunát

hints: allow removing hints

Fixes #111.

Compatibility: it needs a new libkres.so function.  If a wrong version
combination is attempted, the module just cleanly fails to load, though
it writes a slightly confusing message "no such file or directory".
parent 82ccbbd3
......@@ -267,6 +267,21 @@ int kr_zonecut_del(struct kr_zonecut *cut, const knot_dname_t *ns, const knot_rd
return ret;
}
int kr_zonecut_del_all(struct kr_zonecut *cut, const knot_dname_t *ns)
{
if (!cut || !ns) {
return kr_error(EINVAL);
}
/* Find the address list; then free and remove it. */
pack_t *pack = kr_zonecut_find(cut, ns);
if (pack == NULL) {
return kr_error(ENOENT);
}
free_addr_set((const char *)ns, pack, cut->pool);
return map_del(&cut->nsset, (const char *)ns);
}
pack_t *kr_zonecut_find(struct kr_zonecut *cut, const knot_dname_t *ns)
{
if (!cut || !ns) {
......
......@@ -104,6 +104,15 @@ int kr_zonecut_add(struct kr_zonecut *cut, const knot_dname_t *ns, const knot_rd
KR_EXPORT
int kr_zonecut_del(struct kr_zonecut *cut, const knot_dname_t *ns, const knot_rdata_t *rdata);
/**
* Delete all addresses associated with the given name.
* @param cut
* @param ns name server name
* @return 0 or error code
*/
KR_EXPORT
int kr_zonecut_del_all(struct kr_zonecut *cut, const knot_dname_t *ns);
/**
* Find nameserver address list in the zone cut.
*
......
......@@ -30,7 +30,7 @@ Properties
:param string path: path to hosts file, default: ``"/etc/hosts"``
:return: ``{ result: bool }``
Load specified hosts file.
.. function:: hints.get(hostname)
......@@ -45,7 +45,14 @@ Properties
:param string pair: ``hostname address`` i.e. ``"localhost 127.0.0.1"``
:return: ``{ result: bool }``
Set hostname - address pair hint.
Add a hostname - address pair hint.
.. function:: hints.del(pair)
:param string pair: ``hostname address`` i.e. ``"localhost 127.0.0.1"``, or just ``hostname``
:return: ``{ result: bool }``
Remove a hostname - address pair hint. If address is omitted, all addresses for the given name are deleted.
.. function:: hints.root()
......@@ -76,4 +83,4 @@ Properties
}
.. tip:: A good rule of thumb is to select only a few fastest root hints. The server learns RTT and NS quality over time, and thus tries all servers available. You can help it by preselecting the candidates.
\ No newline at end of file
......@@ -216,6 +216,22 @@ static int parse_addr_str(struct sockaddr_storage *sa, const char *addr)
return 0;
}
/** @warning _NOT_ thread-safe; returns a pointer to static data! */
static const knot_rdata_t * addr2rdata(const char *addr) {
/* Parse address string */
struct sockaddr_storage ss;
if (parse_addr_str(&ss, addr) != 0) {
return NULL;
}
/* Build RDATA */
static knot_rdata_t rdata_arr[RDATA_ARR_MAX];
size_t addr_len = kr_inaddr_len((struct sockaddr *)&ss);
const uint8_t *raw_addr = (const uint8_t *)kr_inaddr((struct sockaddr *)&ss);
knot_rdata_init(rdata_arr, addr_len, raw_addr, 0);
return rdata_arr;
}
static int add_pair(struct kr_zonecut *hints, const char *name, const char *addr)
{
/* Build key */
......@@ -223,20 +239,34 @@ static int add_pair(struct kr_zonecut *hints, const char *name, const char *addr
if (!knot_dname_from_str(key, name, sizeof(key))) {
return kr_error(EINVAL);
}
const knot_rdata_t *rdata = addr2rdata(addr);
if (!rdata) {
return kr_error(EINVAL);
}
/* Parse address string */
struct sockaddr_storage ss;
if (parse_addr_str(&ss, addr) != 0) {
return kr_zonecut_add(hints, key, rdata);
}
/** For a given name, remove either one address or all of them (if == NULL). */
static int del_pair(struct kr_zonecut *hints, const char *name, const char *addr)
{
/* Build key */
knot_dname_t key[KNOT_DNAME_MAXLEN];
if (!knot_dname_from_str(key, name, sizeof(key))) {
return kr_error(EINVAL);
}
/* Build RDATA */
size_t addr_len = kr_inaddr_len((struct sockaddr *)&ss);
const uint8_t *raw_addr = (const uint8_t *)kr_inaddr((struct sockaddr *)&ss);
/* @warning _NOT_ thread-safe */
static knot_rdata_t rdata_arr[RDATA_ARR_MAX];
knot_rdata_init(rdata_arr, addr_len, raw_addr, 0);
return kr_zonecut_add(hints, key, rdata_arr);
if (addr) {
/* Remove the pair. */
const knot_rdata_t *rdata = addr2rdata(addr);
if (!rdata) {
return kr_error(EINVAL);
}
return kr_zonecut_del(hints, key, rdata);
} else {
/* Remove the whole name. */
return kr_zonecut_del_all(hints, key);
}
}
static int load_map(struct kr_zonecut *hints, FILE *fp)
......@@ -327,6 +357,25 @@ static char* hint_set(void *env, struct kr_module *module, const char *args)
return result;
}
static char* hint_del(void *env, struct kr_module *module, const char *args)
{
struct kr_zonecut *hints = module->data;
auto_free char *args_copy = strdup(args);
int ret = -1;
char *addr = strchr(args_copy, ' ');
if (addr) {
*addr = '\0';
++addr;
}
ret = del_pair(hints, args_copy, addr);
char *result = NULL;
if (-1 == asprintf(&result, "{ \"result\": %s }", ret == 0 ? "true" : "false"))
result = NULL;
return result;
}
/** @internal Pack address list into JSON array. */
static JsonNode *pack_addrs(pack_t *pack)
{
......@@ -471,6 +520,7 @@ struct kr_prop *hints_props(void)
{
static struct kr_prop prop_list[] = {
{ &hint_set, "set", "Set {name, address} hint.", },
{ &hint_del, "del", "Delete one {name, address} hint or all addresses for the name.", },
{ &hint_get, "get", "Retrieve hint for given name.", },
{ &hint_root, "root", "Replace root hints set (empty value to return current list).", },
{ NULL, NULL, NULL }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment